[node.js] Node.js에서 POST 데이터를 처리하는 방법?

Node.jsform[method="post"] 의 HTTP POST메소드에서 전송 된 양식 데이터 ( ) 및 파일 업로드를 어떻게 추출 합니까?

나는 googled 문서를 읽었으며 아무것도 찾지 못했습니다.

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

도서관이나 해킹이 있습니까?



답변

당신이 사용하는 경우 익스프레스 (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)
});


답변

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

예를 들어, inputname 필드 가 있다면 age변수를 사용하여 액세스 할 수 있습니다 post.

console.log(post.age);


답변

누군가 RAM을 넘치려고하면 연결을 끊어야합니다!

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

        });
    }
}


답변

여기에 많은 답변이 더 이상 모범 사례가 아니거나 설명하지 않으므로이 글을 쓰는 이유입니다.

기초

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를 아약스 의 기본 콘텐츠 형식으로 호출 한 다음 콘텐츠 형식입니다 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 인 경우 qs.parse 대신 JSON.parse를 사용하면 됩니다 .

파일을 다루거나 멀티 파트 컨텐츠 유형을 처리하는 경우, 그와 관련된 모든 고통을 제거하는 강력한 것 같은 것을 사용해야합니다. 멀티 파트 콘텐츠를위한 유용한 링크 및 모듈을 게시 한이 다른 답변 을 살펴보십시오 .

내용을 파싱하고 싶지 않고 다른 곳으로 전달하는 경우, 예를 들어 다른 http 요청에 데이터로 보내거나 파일에 저장하십시오. 버퍼링보다는 파이핑하는 것이 코드를 작성하고, 압력을 더 잘 처리하며, 메모리가 적게 들고 경우에 따라 더 빠릅니다.

콘텐츠를 파일로 저장하려면 다음을 수행하십시오.

 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 모듈

단순히 콘텐츠를 버퍼링하고 파싱하기 위해 HTTP 요청 본문을 사용하는 방법에 대해 위에서 설명했지만이 모듈 중 하나를 사용하면 가장자리를 더 잘 처리 할 수 ​​있으므로 직접 구현하는 것이 좋습니다. Express의 경우 body-parser를 사용하는 것이 좋습니다 . koa의 경우 비슷한 모듈이 있습니다.

프레임 워크를 사용하지 않으면 이 좋습니다.


답변

여기에 게시 된 다른 답변과 기사를 기반으로하는 매우 간단한 프레임 워크 래퍼가 있습니다.

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으로 인코딩 한 다음 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));
        });
    }
}


답변

웹 프레임 워크를 설치하지 않고이 사소한 작업을 수행하는 방법을 궁금해하는 사람은 이것을 함께 관리했습니다. 생산 준비가 거의되지 않았지만 작동하는 것 같습니다.

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