Как вы извлекаете данные POST в узле.Джей?


как вы извлекаете данные форма (form[method="post"]) и загрузка файлов, отправленных с HTTP POST метод узел.js?

Я прочитал документацию, погуглил и ничего не нашел.

function (request, response) {
    //request.post????
}

есть ли библиотека или Хак?

23 510

23 ответа:

Если вы используете Экспресс (высокопроизводительная, высококлассная веб-разработка для узла.js), вы можете сделать это:

HTML:

<form method="post" action="/">
    <input type="text" name="user[name]">
    <input type="text" name="user[email]">
    <input type="submit" value="Submit">
</form>

JavaScript:

app.use(express.bodyParser());

app.post('/', function(request, response){
    console.log(request.body.user.name);
    console.log(request.body.user.email);
});

обновлено 1 / июнь / 2016:

выше метод не рекомендуется использовать так:

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)
});

можно использовать 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 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 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);

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

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

при обратном вызове http.createServer вызывается, когда сервер фактически получил все заголовки для запроса, но возможно, что данные еще не были получены, поэтому мы должны ждать его. Элемент http request object (a http.Экземпляр IncomingMessage) на самом деле читабельныйпоток. В читаемые потоки всякий раз, когда приходит кусок данных, a 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)

если вы попробуете это, вы увидите блоки буфера. Если вы не имеете дело с двоичными данными и должны работать со строками вместо этого я предлагаю использовать запрос.метод 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)

здесь буфера.функция concat используется, который просто объединяет все буферы и возвращает один большой буфер. Вы также можете использовать функция concat-трансляция модуль который делает то же:

const http = require('http');
const concat = require('concat-stream');
http.createServer((request, response) => {
  concat(request, data => {
    console.log('Data: ', data);
  });
}).listen(8080)

если вы пытаетесь принять HTML-формы после отправки без файлов или передачи jQuery ajax вызовы с типом контента по умолчанию, то тип контента application/x-www-form-urlencoded С uft-8 кодировка. Вы можете использовать модуль querystring чтобы де-сериализовать его и получить доступ к свойствам:

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.разбор вместо qs.разбор.

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

если вы не хотите анализировать содержимое, а скорее передать его в другое место, например, отправить его на другой http-запрос в качестве данных или сохранить его в файл, я предлагаю piping it вместо того, чтобы буферизировать его, так как это будет меньше кода, лучше справляется с обратным давлением, это займет меньше памяти и в некоторых случаях быстрее.

так что если вы хотите сохранить содержимое в файл:

 http.createServer((request, response) => {
   request.pipe(fs.createWriteStream('./request'));
 }).listen(8080)

как отмечали другие ответы имейте в виду, что вредоносные клиенты могут отправить вам огромное количество данных для сбоя вашего приложения или заполнить вашу память, чтобы защитить это, убедитесь, что вы отбрасываете запросы, которые выдают данные пройти определенный предел. Если вы не используете библиотеку для обработки входящих данных. Я бы предложил использовать что-то вроде stream-meter который может прервать запрос, если достигает указанного предела:

limitedStream = request.pipe(meter(1e7));
limitedStream.on('data', ...);
limitedStream.on('end', ...);

или

request.pipe(meter(1e7)).pipe(createWriteStream(...));

или

concat(request.pipe(meter(1e7)), ...);

также попробуйте использовать модули npm, а не реализовывать их самостоятельно, поскольку они, вероятно, лучше справятся с краевыми случаями. Для экспресс я предлагаю использовать body-parser. Для КоА, есть похожие модуля.

если вы не используете основу, тело неплохо.

для тех, кто задается вопросом, как сделать эту тривиальную задачу без установки веб-фреймворка мне удалось хлопнуть это вместе. Вряд ли готов, но это, кажется, работает.

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 узел.в 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);
    // ...
});

Если вы не хотите, чтобы разделить ваши данные вместе с 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
});

этот подход изменяет входящий запрос, но как только вы закончите свой ответ на запрос будет собран "мусор", так что не должно быть проблемой.

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

есть несколько способов сделать это. Однако самый быстрый способ, который я знаю, - это использовать экспресс.библиотека js с body-parser.

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 предложил.

Если вы используете Экспресс.js, прежде чем вы сможете получить доступ к req.body, вы должны добавить middleware bodyParser:

app.use(express.bodyParser());

тогда вы можете попросить

req.body.user

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

она зарегистрирована в узел.модули на JS

  1. установить 'body-parser' от НПМ.
  2. откройте app.ts -- > write ->var bodyParser = require('body-parser');
  3. тогда вам нужно написать app.use(bodyParser.json()) на app.ts модуль
  4. имейте в виду, что вы включили app.use(bodyParser.json()) в верхней части или перед любым объявлением модуля. Например:app.use(bodyParser.json()) app.use('/user',user);

  5. затем использовать var postdata = req.body;

для тех, кто использует raw binary POST upload без кодирования накладных расходов можно использовать:

клиент:

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!");
  });
});

ограничить размер сообщения избегайте наводнения вашего узла приложения. Есть отличный raw-body модуль, подходящий как для экспресс, так и для подключения, что может помочь вам ограничить запрос по размеру и длине.

Я нашел видео, которое объясняет, как добиться этого: 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);

Если это связано с загрузкой файла, браузер обычно отправляет его как "multipart/form-data" контент-тип. Вы можете использовать это в таких случаях

var multipart = require('multipart');
multipart.parse(req)

ссылка 1

Ссылка 2

на полях формы, как эти

   <input type="text" name="user[name]" value="MyName">
   <input type="text" name="user[email]" value="myemail@somewherefarfar.com">

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

сейчас я использую ответ Кейси Чу, но с "qs" вместо модуля" querystring". Это модуль "body-parser" использует, а также. Поэтому, если вы хотите вложенные данные, вы должны установить 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.
        });
    }
}

Если вы предпочитаете использовать чистый узел.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}`);
});

вы можете извлечь параметр post без использования 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>

Я надеюсь, что это будет работать для вас. Спасибо.