Node.js-Express를 사용하여 원시 요청 본문 가져 오기


답변:


89

편집 2 : 본문 파서 모듈의 1.15.2 릴리스 에서는 본문을 Buffer 로 반환하는 원시 모드를 도입 합니다 . 기본적으로 deflate 및 gzip 압축 해제도 자동으로 처리합니다. 사용 예 :

var bodyParser = require('body-parser');
app.use(bodyParser.raw(options));

app.get(path, function(req, res) {
  // req.body is a Buffer object
});

기본적으로 options개체에는 다음과 같은 기본 옵션이 있습니다.

var options = {
  inflate: true,
  limit: '100kb',
  type: 'application/octet-stream'
};

원시 파서가 이외의 다른 MIME 유형을 구문 분석 application/octet-stream하도록하려면 여기에서 변경해야합니다. 또한 같은 와일드 카드 매칭을 지원 */*하거나 */application.


참고 : 다음 답변은 미들웨어가 여전히 프레임 워크와 번들로 제공되는 Express 4 이전 버전에 대한 것입니다. 현대에 해당하는 것은 body-parser입니다. 별도로 설치해야하는 모듈입니다.

rawBodyExpress 의 속성은 한 번 사용할 수 있었지만 버전 1.5.1부터 제거되었습니다. 원시 요청 본문을 얻으려면 bodyParser를 사용하기 전에 미들웨어를 넣어야합니다. 여기 에서 GitHub 토론을 읽을 수도 있습니다 .

app.use(function(req, res, next) {
  req.rawBody = '';
  req.setEncoding('utf8');

  req.on('data', function(chunk) { 
    req.rawBody += chunk;
  });

  req.on('end', function() {
    next();
  });
});
app.use(express.bodyParser());

해당 미들웨어는 실제 데이터 스트림에서 읽고이를 rawBody요청 속성에 저장합니다 . 그런 다음 다음과 같이 원시 본문에 액세스 할 수 있습니다.

app.post('/', function(req, res) {
  // do something with req.rawBody
  // use req.body for the parsed body
});

편집 : 이 메서드와 bodyParser가 공존하는 것을 거부하는 것 같습니다. 왜냐하면 하나는 다른 하나보다 먼저 요청 스트림을 소비하여 둘 중 하나가 두 번째로 실행되지 end않아 절대 호출하지 않고 next()응용 프로그램을 중단하기 때문입니다.

가장 간단한 해결책은 Connect의 JSON 파서 57 행에서 찾을 수있는 bodyParser의 소스를 수정하는 것 입니다. 이것이 수정 된 버전의 모습입니다.

var buf = '';
req.setEncoding('utf8');
req.on('data', function(chunk){ buf += chunk });
req.on('end', function() {
  req.rawBody = buf;
  var first = buf.trim()[0];
  ...
});

다음 위치에서 파일을 찾을 수 있습니다.

/node_modules/express/node_modules/connect/lib/middleware/json.js.


우리는 이것을 할 수없는 것 같습니다. 이 코드를 추가하면 \ node_modules \ express \ node_modules \ connect \ lib \ middleware \ urlencoded.js의 이벤트가 실행되지 않습니다. req.on ( "data"), req.on ( "end")가 실행되지 않았습니다 .
haitao_wu

코드를 추가 한 후이 코드를 사용하여 게시물을 처리합니다. app.post ( "/ ajax", function (req, res) {res.send ( 'hello world, post');}); 내 요청의 콘텐츠 형식은 application / x-www-form-urlencoded로, 때 서버하지 않습니다 응답 "안녕하세요 세계, 포스트"
haitao_wu

제 경우에는 파일의 위치가 올바르지 않습니다 .. express (> 4.0.0)의 node_modules에 연결 모듈이 없습니다. 아직 새 위치를 찾지 못했습니다
Sam Vloeberghs

Connect는 Express 4에서 종속성이 아니므로 Body Parser 모듈을 포함하지 않습니다. 여전히 필요하다면 여기에서 찾을 수 있습니다 .
hexacyanide

1
@hexacyanide 답변을 업데이트하고 최신 body-parser 미들웨어에 대한 참조를 포함 해 주 시겠습니까? 모듈은 이제 raw-body-parser 미들웨어를 포함 합니다. 이것은 원시 본문을 얻는 방법을 찾는 Google 직원에게 도움이 될 수 있습니다.
eAbi

47

bodyParser의 verify콜백을 사용하여 bodyParser와 잘 어울리는 솔루션을 얻었 습니다. 이 코드에서는 콘텐츠의 sha1을 얻고 원시 본문도 가져 오는 데 사용하고 있습니다.

app.use(bodyParser.json({
    verify: function(req, res, buf, encoding) {

        // sha1 content
        var hash = crypto.createHash('sha1');
        hash.update(buf);
        req.hasha = hash.digest('hex');
        console.log("hash", req.hasha);

        // get rawBody        
        req.rawBody = buf.toString();
        console.log("rawBody", req.rawBody);

    }
}));

저는 Node.js와 express.js (어제 시작되었습니다. 문자 그대로!)를 처음 사용하므로이 솔루션에 대한 의견을 듣고 싶습니다.


3
이 솔루션이 정말 마음에 듭니다. 내가 필요로하는 전부 였기 때문에 req.rawBody = buf.toString();나머지는 verify함수에서 제외하고 포함 시켰고 아름답게 작동했습니다. bodyParser 소스 코드를 변경할 필요가 없습니다!
그렉

+1하지만 이제 내 문제는이 요청이 이전에 전송되었는지 확인하기 위해 비동기 함수가 필요하다는 것입니다. /
Renato Gama

3
아주 좋아. 나는 제안 할 수 있습니다req.rawBody = buf.toString(encoding);
shaharsol

2
application/json요청 만 캡처 합니다
Pavel Evstigneev

35

이 솔루션은 저에게 효과적이었습니다.

var rawBodySaver = function (req, res, buf, encoding) {
  if (buf && buf.length) {
    req.rawBody = buf.toString(encoding || 'utf8');
  }
}

app.use(bodyParser.json({ verify: rawBodySaver }));
app.use(bodyParser.urlencoded({ verify: rawBodySaver, extended: true }));
app.use(bodyParser.raw({ verify: rawBodySaver, type: '*/*' }));

req.on('data', function(chunk) { });청크 요청 본문에서 작동하지 않는 솔루션을 사용할 때 .


이것은 요청의 다양한 부분에서 들어오는 데이터의 모든 주요 시나리오를 처리했습니다.
TWright

2
Shopify 앱 웹훅에 대한 hmac을 확인하려고했는데 이것이 저에게 효과적이었습니다. 대략 다음 예제를 따랐습니다 : gist.github.com/andjosh/5c4f0244914adfd312e4 .
Chad Johnson

29

json, urlencoded 등을 지원하려는 경우 bodyParser에서 제대로 재생되지 않으므로 다른 답변에주의하십시오. bodyParser와 함께 작동하도록하려면 처리기를 조건화하여 Content-Type헤더 에만 등록해야 합니다. bodyParser 자체처럼

와 요청의 원시 본문 내용 얻으려면 Content-Type: "text/plain"req.rawBody당신이 할 수 있습니다 :

app.use(function(req, res, next) {
  var contentType = req.headers['content-type'] || ''
    , mime = contentType.split(';')[0];

  if (mime != 'text/plain') {
    return next();
  }

  var data = '';
  req.setEncoding('utf8');
  req.on('data', function(chunk) {
    data += chunk;
  });
  req.on('end', function() {
    req.rawBody = data;
    next();
  });
});

3
+1. 위의 솔루션 중 하나를 시도한 다음 모든 GET 및 json 게시물이 실패했습니다. 위의 솔루션은 질문에 대한 기술적으로 정확하지만 둘 이상의 형식의 데이터를 사용하여 더 다양한 요청을 처리하는 경우 이것이 필요합니다.

여기에 데이터는 무엇입니까? UI에서 보내는 변수입니까?
Saras Arya 2015 년

app.use(bodyParser.urlencoded({limit: '80mb', extended: true})); app.use(bodyParser.json({limit: '80mb'})); app.use(bodyParser.raw({type: 'application/octet-stream'})) 이것은 또한 할 것입니다.
Soumya Kanti

15

이것은 위의 hexacyanide의 대답에 대한 변형입니다. 이 미들웨어는 '데이터'이벤트도 처리하지만 'next'를 호출하기 전에 데이터가 소비 될 때까지 기다리지 않습니다. 이렇게하면이 미들웨어와 bodyParser가 공존하여 스트림을 병렬로 소비 할 수 있습니다.

app.use(function(req, res, next) {
  req.rawBody = '';
  req.setEncoding('utf8');

  req.on('data', function(chunk) { 
    req.rawBody += chunk;
  });

  next();
});
app.use(express.bodyParser());


2
이것은 조기에 잘리는 긴 몸에는 효과가없는 것 같습니다.
Adam Lockhart

완벽하게 일했고 나를 구했습니다. 감사합니다.
hakazvaka

나는 이것이 큰 파일에서도 작동한다는 것을 확인하고 있습니다. 1.5MB의 텍스트 파일을 보내려고했는데 전체 데이터가 제대로 수신되었습니다. 감사합니다
ATOzTOA 2016 년

@AdamLockhart-귀하의 요청이 절단 된 크기는 얼마입니까?
UpTheCreek

@UpTheCreek, 오래되었습니다. 확실하지 않다. 내 최신 항목은이 스 니펫을 사용하지 않지만 다른 사람이 문제를보고하지 않으면 수정 된 버그 일 수 있습니다.
아담 록 하트

-1

본문 파서 사용 본문을 다음과 같이 구문 분석합니다.

app.use(bodyParser.text());

app.use(bodyParser.urlencoded());

app.use(bodyParser.raw());

app.use(bodyParser.json());

즉. 원시 텍스트 파일을 얻으려면 다음을 실행하십시오..text() .

그것이 body-parser가 현재 지원하는 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.