Відповіді:
Якщо ви використовуєте Express (високоефективна, висококласна веб-розробка для Node.js), ви можете це зробити:
HTML:
<form method="post" action="/">
<input type="text" name="user[name]">
<input type="text" name="user[email]">
<input type="submit" value="Submit">
</form>
API клієнта:
fetch('/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
user: {
name: "John",
email: "john@example.com"
}
})
});
Node.js: (оскільки Express v4.16.0)
// Parse URL-encoded bodies (as sent by HTML forms)
app.use(express.urlencoded());
// Parse JSON bodies (as sent by API clients)
app.use(express.json());
// Access the parse results as request.body
app.post('/', function(request, response){
console.log(request.body.user.name);
console.log(request.body.user.email);
});
Node.js: (для Express <4.16.0)
const bodyParser = require("body-parser");
/** bodyParser.urlencoded(options)
* Parses the text as URL encoded data (which is how browsers tend to send form data from regular forms set to POST)
* and exposes the resulting object (containing the keys and values) on req.body
*/
app.use(bodyParser.urlencoded({
extended: true
}));
/**bodyParser.json(options)
* Parses the text as JSON and exposes the resulting object on req.body.
*/
app.use(bodyParser.json());
app.post("/", function (req, res) {
console.log(req.body.user.name)
});
app.use(express.bodyParser());
.
Ви можете використовувати querystring
модуль:
var qs = require('querystring');
function (request, response) {
if (request.method == 'POST') {
var body = '';
request.on('data', function (data) {
body += data;
// Too much POST data, kill the connection!
// 1e6 === 1 * Math.pow(10, 6) === 1 * 1000000 ~~~ 1MB
if (body.length > 1e6)
request.connection.destroy();
});
request.on('end', function () {
var post = qs.parse(body);
// use post['blah'], etc.
});
}
}
Наприклад, якщо у вас є input
поле з ім'ям age
, ви можете отримати доступ до нього за допомогою змінної post
:
console.log(post.age);
var POST = qs.parse(body); // use POST
лише для ноб, таких як я: коли ім'я текстового поля введення "користувач", Post.user
покаже дані цього поля. наприкладconsole.log(Post.user);
readable
зворотний виклик, а не вбудовувати дані в рядок тіла. Як тільки його звільняють, тіло стає доступним черезrequest.read();
req.connection.destroy();
не заважає виконувати зворотні дзвінки! Наприклад, зворотний виклик "в кінці" буде виконаний з усіченим корпусом! Мабуть, це не те, що ти хочеш ...
Не забудьте перервати з'єднання, якщо хтось намагається залити вашу ОЗУ!
var qs = require('querystring');
function (request, response) {
if (request.method == 'POST') {
var body = '';
request.on('data', function (data) {
body += data;
// 1e6 === 1 * Math.pow(10, 6) === 1 * 1000000 ~~~ 1MB
if (body.length > 1e6) {
// FLOOD ATTACK OR FAULTY CLIENT, NUKE REQUEST
request.connection.destroy();
}
});
request.on('end', function () {
var POST = qs.parse(body);
// use POST
});
}
}
var POST = qs.parse(body); // use POST
лише для нообів: коли назва поля введення тексту "користувач", Post.user покаже дані цього поля. наприклад console.log (Post.user);
Багато відповідей тут вже не є гарною практикою або нічого не пояснюють, тому я це пишу.
Коли викликається зворотний виклик http.createServer, це коли сервер фактично отримав усі заголовки для запиту, але можливо, дані ще не отримані, тому нам доведеться чекати. Об'єкт запиту http (екземпляр http.IncomingMessage) - це фактично читабельний потік . У читаних потоках щоразу, коли надходить фрагмент даних, подія випромінюється (якщо припустити, що ви зареєстрували зворотний дзвінок до неї), і коли всі фрагменти надійшли, подія випромінюється. Ось приклад того, як ви слухаєте події:data
end
http.createServer((request, response) => {
console.log('Now we have a http message with headers but no data yet.');
request.on('data', chunk => {
console.log('A chunk of data has arrived: ', chunk);
});
request.on('end', () => {
console.log('No more data');
})
}).listen(8080)
Якщо ви спробуєте це, ви помітите, що шматки буфери . Якщо ви не маєте справу з бінарними даними та вам потрібно працювати з рядками, я пропоную використовувати метод request.setEncoding, який спричиняє потоки випромінювання рядків, інтерпретовані заданим кодуванням та належним чином обробляють багатобайтові символи.
Тепер ви, мабуть, не зацікавлені в кожному фрагменті самостійно, тому в цьому випадку, ймовірно, ви хочете передати його таким чином:
http.createServer((request, response) => {
const chunks = [];
request.on('data', chunk => chunks.push(chunk));
request.on('end', () => {
const data = Buffer.concat(chunks);
console.log('Data: ', data);
})
}).listen(8080)
Тут використовується Buffer.concat , який просто об'єднує всі буфери і повертає один великий буфер. Ви також можете використовувати модуль concat-stream, який робить те саме:
const http = require('http');
const concat = require('concat-stream');
http.createServer((request, response) => {
concat(request, data => {
console.log('Data: ', data);
});
}).listen(8080)
Якщо ви намагаєтеся прийняти HTML-форми подання POST без файлів або передачі jQuery ajax- дзвінків із типом контенту за замовчуванням, то тип вмісту application/x-www-form-urlencoded
з uft-8
кодуванням. Ви можете використовувати модуль запитів для десеріалізації та доступу до властивостей:
const http = require('http');
const concat = require('concat-stream');
const qs = require('querystring');
http.createServer((request, response) => {
concat(request, buffer => {
const data = qs.parse(buffer.toString());
console.log('Data: ', data);
});
}).listen(8080)
Якщо ваш тип вмісту замість JSON, ви можете просто використовувати JSON.parse замість qs.parse .
Якщо ви маєте справу з файлами або обробляєте багатоповерховий тип вмісту, то в такому випадку вам слід використовувати щось на зразок грізного, що позбавляє всіх болю від боротьби з ним. Подивіться на цю іншу мою відповідь, де я розмістив корисні посилання та модулі для багаточастинного контенту.
Якщо ви не хочете проаналізувати вміст, а скоріше передати його десь в іншому місці, наприклад, надішліть його іншому http-запиту як дані або збережіть у файл, я пропоную передати його замість буферизації, оскільки його буде менше код, краще справляється з тиском, це займе менше пам'яті, а в деяких випадках і швидше.
Отже, якщо ви хочете зберегти вміст у файлі:
http.createServer((request, response) => {
request.pipe(fs.createWriteStream('./request'));
}).listen(8080)
Як зазначаються інші відповіді, майте на увазі, що зловмисні клієнти можуть надіслати вам величезну кількість даних, щоб зламати вашу програму або заповнити вашу пам'ять, щоб захистити, щоб ви відмовилися від запитів, які випромінюють дані, пройшли певний ліміт. Якщо ви не використовуєте бібліотеку для обробки вхідних даних. Я б запропонував використовувати щось на зразок потокового метра, який може перервати запит, якщо досягнутий визначений ліміт:
limitedStream = request.pipe(meter(1e7));
limitedStream.on('data', ...);
limitedStream.on('end', ...);
або
request.pipe(meter(1e7)).pipe(createWriteStream(...));
або
concat(request.pipe(meter(1e7)), ...);
Хоча я описав вище про те, як можна використовувати тіло запиту HTTP, для простого буферизації та розбору вмісту, я пропоную використовувати один з цих модулів, а не реалізувати самостійно, оскільки вони, ймовірно, краще обробляють крайові випадки. Для експресу пропоную використовувати body-аналізатор . Для коа є аналогічний модуль .
Якщо ви не використовуєте рамку, тіло цілком добре.
request
повторно використовується і request.on('end')
викликається кілька разів? Як я можу цього уникнути?
request.on('end', ...)
буде викликано.
Ось дуже проста обгортка без рамки на основі інших відповідей та статей, розміщених тут:
var http = require('http');
var querystring = require('querystring');
function processPost(request, response, callback) {
var queryData = "";
if(typeof callback !== 'function') return null;
if(request.method == 'POST') {
request.on('data', function(data) {
queryData += data;
if(queryData.length > 1e6) {
queryData = "";
response.writeHead(413, {'Content-Type': 'text/plain'}).end();
request.connection.destroy();
}
});
request.on('end', function() {
request.post = querystring.parse(queryData);
callback();
});
} else {
response.writeHead(405, {'Content-Type': 'text/plain'});
response.end();
}
}
Приклад використання:
http.createServer(function(request, response) {
if(request.method == 'POST') {
processPost(request, response, function() {
console.log(request.post);
// Use request.post here
response.writeHead(200, "OK", {'Content-Type': 'text/plain'});
response.end();
});
} else {
response.writeHead(200, "OK", {'Content-Type': 'text/plain'});
response.end();
}
}).listen(8000);
response.post
а не більш логічним request.post
. Я оновив публікацію.
Це буде чистіше, якщо ви кодуєте свої дані в JSON , а потім надсилаєте їх до Node.js.
function (req, res) {
if (req.method == 'POST') {
var jsonString = '';
req.on('data', function (data) {
jsonString += data;
});
req.on('end', function () {
console.log(JSON.parse(jsonString));
});
}
}
qs.parse()
, JSON.parse()
перевернули тіло будь-що - то придатні до вживання. Приклад:, var post = JSON.parse(body);
потім перейдіть до даних за допомогою post.fieldname
. (Мораль історії, якщо вас бентежить те, що ви бачите, не забувайте typeof
!)
request.setEncoding
для правильної роботи, інакше вона не може належним чином обробляти символи, що не входять до списку.
Для тих, хто цікавиться, як зробити це тривіальне завдання, не встановлюючи веб-рамки, мені вдалося зірвати це разом. Навряд чи готове виробництво, але, здається, працює.
function handler(req, res) {
var POST = {};
if (req.method == 'POST') {
req.on('data', function(data) {
data = data.toString();
data = data.split('&');
for (var i = 0; i < data.length; i++) {
var _data = data[i].split("=");
POST[_data[0]] = _data[1];
}
console.log(POST);
})
}
}
Ви можете використовувати body-parser
проміжне програмне забезпечення для розбору тіла Node.js.
Перше навантаження body-parser
$ npm install body-parser --save
Деякі приклади коду
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(function (req, res) {
var post_data = req.body;
console.log(post_data);
})
Більше документації можна знайти тут
Довідка: https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/
let body = [];
request.on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
body = Buffer.concat(body).toString();
// at this point, `body` has the entire request body stored in it as a string
});
Ось як це можна зробити, якщо ви використовуєте формат, який можна формувати :
var formidable = require("formidable");
var form = new formidable.IncomingForm();
form.parse(request, function (err, fields) {
console.log(fields.parameter1);
console.log(fields.parameter2);
// ...
});
Якщо ви віддаєте перевагу використовувати чистий Node.js, ви можете витягнути дані POST, як показано нижче:
// Dependencies
const StringDecoder = require('string_decoder').StringDecoder;
const http = require('http');
// Instantiate the HTTP server.
const httpServer = http.createServer((request, response) => {
// Get the payload, if any.
const decoder = new StringDecoder('utf-8');
let payload = '';
request.on('data', (data) => {
payload += decoder.write(data);
});
request.on('end', () => {
payload += decoder.end();
// Parse payload to object.
payload = JSON.parse(payload);
// Do smoething with the payload....
});
};
// Start the HTTP server.
const port = 3000;
httpServer.listen(port, () => {
console.log(`The server is listening on port ${port}`);
});
1) Встановити 'body-parser'
з npm.
2) Потім у ваших app.ts
var bodyParser = require('body-parser');
3) тоді потрібно писати
app.use(bodyParser.json())
у додатках модулі
4) майте на увазі, що ви включаєте
app.use(bodyParser.json())
вгорі або перед будь-яким оголошенням модуля.
Наприклад:
app.use(bodyParser.json())
app.use('/user',user);
5) Потім використовуйте
var postdata = req.body;
Якщо ви не хочете обробляти свої дані разом із data
зворотним дзвоном, ви завжди можете використовувати readable
зворотний виклик так:
// Read Body when Available
request.on("readable", function(){
request.body = '';
while (null !== (request.body += request.read())){}
});
// Do something with it
request.on("end", function(){
request.body //-> POST Parameters as String
});
Цей підхід змінює вхідний запит, але як тільки ви закінчите свою відповідь, запит буде зібраний сміттям, так що це не повинно бути проблемою.
Передовим підходом було б спочатку перевірити розмір тіла, якщо ти боїшся величезних тіл.
request
є нормальним потоком node.js, тому ви можете перевірити request.headers
довжину тіла та скасувати запит, якщо це необхідно.
Існує кілька способів зробити це. Однак найшвидший спосіб, який я знаю, - це використовувати бібліотеку Express.js з аналізатором тіла.
var express = require("express");
var bodyParser = require("body-parser");
var app = express();
app.use(bodyParser.urlencoded({extended : true}));
app.post("/pathpostdataissentto", function(request, response) {
console.log(request.body);
//Or
console.log(request.body.fieldName);
});
app.listen(8080);
Це може працювати для рядків, але я замінюю bodyParser.urlencoded на bodyParser.json, якщо дані POST містять масив JSON.
Більше інформації: http://www.kompulsa.com/how-to-accept-and-parse-post-requests-in-node-js/
POST
Дані потрібно отримувати за допомогою шматочківrequest.on('data', function(chunk) {...})
const http = require('http');
http.createServer((req, res) => {
if (req.method == 'POST') {
whole = ''
req.on('data', (chunk) => {
# consider adding size limit here
whole += chunk.toString()
})
req.on('end', () => {
console.log(whole)
res.writeHead(200, 'OK', {'Content-Type': 'text/html'})
res.end('Data received.')
})
}
}).listen(8080)
Вам слід розглянути можливість додавання обмеження розміру у вказаній позиції, як запропоновано thejh .
setTimeout
якщо закінчується з'єднання через певний проміжок часу, якщо повний запит не буде отриманий у цьому вікні.
Якщо ви використовуєте Express.js , перш ніж отримати доступ до req.body, потрібно додати проміжне програмне забезпечення bodyParser:
app.use(express.bodyParser());
Тоді ви можете попросити
req.body.user
І якщо ви не хочете використовувати весь фреймворк, як Express, але вам також потрібні різні види форм, включаючи завантаження, то формалін може бути хорошим вибором.
Він вказаний у модулях Node.js
Я знайшов відео, в якому пояснюється, як цього досягти: https://www.youtube.com/watch?v=nuw48-u3Yrg
Він використовує модуль "http" за замовчуванням разом з модулями "querystring" та "stringbuilder". Додаток бере два числа (використовуючи два текстових поля) з веб-сторінки та після надсилання повертає суму цих двох (разом із збереженням значень у текстових полях). Це найкращий приклад, який я міг знайти деінде.
Пов'язаний вихідний код:
var http = require("http");
var qs = require("querystring");
var StringBuilder = require("stringbuilder");
var port = 9000;
function getCalcHtml(req, resp, data) {
var sb = new StringBuilder({ newline: "\r\n" });
sb.appendLine("<html>");
sb.appendLine(" <body>");
sb.appendLine(" <form method='post'>");
sb.appendLine(" <table>");
sb.appendLine(" <tr>");
sb.appendLine(" <td>Enter First No: </td>");
if (data && data.txtFirstNo) {
sb.appendLine(" <td><input type='text' id='txtFirstNo' name='txtFirstNo' value='{0}'/></td>", data.txtFirstNo);
}
else {
sb.appendLine(" <td><input type='text' id='txtFirstNo' name='txtFirstNo' /></td>");
}
sb.appendLine(" </tr>");
sb.appendLine(" <tr>");
sb.appendLine(" <td>Enter Second No: </td>");
if (data && data.txtSecondNo) {
sb.appendLine(" <td><input type='text' id='txtSecondNo' name='txtSecondNo' value='{0}'/></td>", data.txtSecondNo);
}
else {
sb.appendLine(" <td><input type='text' id='txtSecondNo' name='txtSecondNo' /></td>");
}
sb.appendLine(" </tr>");
sb.appendLine(" <tr>");
sb.appendLine(" <td><input type='submit' value='Calculate' /></td>");
sb.appendLine(" </tr>");
if (data && data.txtFirstNo && data.txtSecondNo) {
var sum = parseInt(data.txtFirstNo) + parseInt(data.txtSecondNo);
sb.appendLine(" <tr>");
sb.appendLine(" <td>Sum: {0}</td>", sum);
sb.appendLine(" </tr>");
}
sb.appendLine(" </table>");
sb.appendLine(" </form>")
sb.appendLine(" </body>");
sb.appendLine("</html>");
sb.build(function (err, result) {
resp.write(result);
resp.end();
});
}
function getCalcForm(req, resp, data) {
resp.writeHead(200, { "Content-Type": "text/html" });
getCalcHtml(req, resp, data);
}
function getHome(req, resp) {
resp.writeHead(200, { "Content-Type": "text/html" });
resp.write("<html><html><head><title>Home</title></head><body>Want to some calculation? Click <a href='/calc'>here</a></body></html>");
resp.end();
}
function get404(req, resp) {
resp.writeHead(404, "Resource Not Found", { "Content-Type": "text/html" });
resp.write("<html><html><head><title>404</title></head><body>404: Resource not found. Go to <a href='/'>Home</a></body></html>");
resp.end();
}
function get405(req, resp) {
resp.writeHead(405, "Method not supported", { "Content-Type": "text/html" });
resp.write("<html><html><head><title>405</title></head><body>405: Method not supported</body></html>");
resp.end();
}
http.createServer(function (req, resp) {
switch (req.method) {
case "GET":
if (req.url === "/") {
getHome(req, resp);
}
else if (req.url === "/calc") {
getCalcForm(req, resp);
}
else {
get404(req, resp);
}
break;
case "POST":
if (req.url === "/calc") {
var reqBody = '';
req.on('data', function (data) {
reqBody += data;
if (reqBody.length > 1e7) { //10MB
resp.writeHead(413, 'Request Entity Too Large', { 'Content-Type': 'text/html' });
resp.end('<!doctype html><html><head><title>413</title></head><body>413: Request Entity Too Large</body></html>');
}
});
req.on('end', function () {
var formData = qs.parse(reqBody);
getCalcForm(req, resp, formData);
});
}
else {
get404(req, resp);
}
break;
default:
get405(req, resp);
break;
}
}).listen(port);
Для тих, хто використовує необроблене бінарне завантаження POST без кодування накладних витрат, можна використовувати:
клієнт:
var xhr = new XMLHttpRequest();
xhr.open("POST", "/api/upload", true);
var blob = new Uint8Array([65,72,79,74]); // or e.g. recorder.getBlob()
xhr.send(blob);
сервер:
var express = require('express');
var router = express.Router();
var fs = require('fs');
router.use (function(req, res, next) {
var data='';
req.setEncoding('binary');
req.on('data', function(chunk) {
data += chunk;
});
req.on('end', function() {
req.body = data;
next();
});
});
router.post('/api/upload', function(req, res, next) {
fs.writeFile("binaryFile.png", req.body, 'binary', function(err) {
res.send("Binary POST successful!");
});
});
Ви можете використовувати експрес- проміжне програмне забезпечення, в яке зараз вбудований аналізатор тіла. Це означає, що вам потрібно:
import express from 'express'
const app = express()
app.use(express.json())
app.post('/thing', (req, res) => {
console.log(req.body) // <-- this will access the body of the post
res.sendStatus(200)
})
Цей приклад коду - ES6 з Express 4.16.x
ви можете вилучити параметр публікації, не використовуючи express.
1: nmp install multiparty
2: імпорт багатопартійних. якvar multiparty = require('multiparty');
3: `
if(req.method ==='POST'){
var form = new multiparty.Form();
form.parse(req, function(err, fields, files) {
console.log(fields['userfile1'][0]);
});
}
4: і HTML-ФОРМА Є.
<form method=POST enctype=multipart/form-data>
<input type=text name=userfile1><br>
<input type=submit>
</form>
Я сподіваюся, що це спрацює для вас. Дякую.
Обмежте розмір POST, щоб уникнути затоплення додатка на вузлі. Існує чудовий модуль сировини , який підходить як для швидкої, так і для з'єднання, що допоможе вам обмежити запит за розміром і довжиною.
Якщо це стосується завантаження файлу, браузер зазвичай надсилає його як "multipart/form-data"
тип вмісту. Ви можете використовувати це в таких випадках
var multipart = require('multipart');
multipart.parse(req)
На таких формах поля
<input type="text" name="user[name]" value="MyName">
<input type="text" name="user[email]" value="myemail@somewherefarfar.com">
деякі з вищезазначених відповідей не зможуть, оскільки вони підтримують лише плоскі дані.
Наразі я використовую відповідь Кейсі Чу, але з "qs" замість модуля "querystring". Це і модуль «тіло-аналізатор» . Тож якщо ви хочете вкладені дані, ви повинні встановити qs.
npm install qs --save
Потім замініть перший рядок, як:
//var qs = require('querystring');
var qs = require('qs');
function (request, response) {
if (request.method == 'POST') {
var body = '';
request.on('data', function (data) {
body += data;
// Too much POST data, kill the connection!
// 1e6 === 1 * Math.pow(10, 6) === 1 * 1000000 ~~~ 1MB
if (body.length > 1e6)
request.connection.destroy();
});
request.on('end', function () {
var post = qs.parse(body);
console.log(post.user.name); // should work
// use post['blah'], etc.
});
}
}
Ви можете легко надіслати та отримати відповідь на запит POST, скориставшись "Запит - спрощений клієнт HTTP" та Javascript Promise.
var request = require('request');
function getData() {
var options = {
url: 'https://example.com',
headers: {
'Content-Type': 'application/json'
}
};
return new Promise(function (resolve, reject) {
var responseData;
var req = request.post(options, (err, res, body) => {
if (err) {
console.log(err);
reject(err);
} else {
console.log("Responce Data", JSON.parse(body));
responseData = body;
resolve(responseData);
}
});
});
}
Вам потрібно використовувати bodyParser (), якщо ви хочете, щоб дані форми були доступні у req.body. body-parser аналізує ваш запит і перетворює його у формат, з якого ви можете легко отримати відповідну інформацію, яка вам може знадобитися.
Наприклад, припустімо, що у вас на кордоні форма реєстрації. Ви заповнюєте його та просите сервер десь зберегти дані.
Вилучення імені користувача та пароля з вашого запиту відбувається так само просто, як нижче, якщо ви використовуєте body-parser.
…………………………………………………….
var loginDetails = {
username : request.body.username,
password : request.body.password
};
ОДИН ЛІНЕР без ПЕРЕГЛЯДУВАННЯ
Якщо ви публікуєте наступні дані, 'name':'ABC'
тоді ви можете їх проаналізувати за допомогою наступного вкладиша,
require('url').parse(req.url, true).query.name