Node.js - lấy nội dung yêu cầu thô bằng Express


Câu trả lời:


89

Chỉnh sửa 2: Bản phát hành 1.15.2 của mô-đun phân tích cú pháp nội dung giới thiệu chế độ thô , trả về nội dung dưới dạng Bộ đệm . Theo mặc định, nó cũng tự động xử lý giải nén deflate và gzip. Ví dụ sử dụng:

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

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

Theo mặc định, optionsđối tượng có các tùy chọn mặc định sau:

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

Nếu bạn muốn trình phân tích cú pháp thô của mình phân tích cú pháp các kiểu MIME khác application/octet-stream, bạn sẽ cần thay đổi nó tại đây. Nó cũng sẽ hỗ trợ đối sánh ký tự đại diện chẳng hạn như */*hoặc */application.


Lưu ý: Câu trả lời sau dành cho các phiên bản trước Express 4, nơi phần mềm trung gian vẫn được đóng gói cùng với khung. Tương đương hiện đại là mô-đun body-parser , phải được cài đặt riêng.

Các rawBodybất động sản cấp tốc đã từng có, nhưng loại bỏ kể từ phiên bản 1.5.1. Để có được phần thân yêu cầu thô, bạn phải đặt một số phần mềm trung gian trước khi sử dụng bodyParser. Bạn cũng có thể đọc một cuộc thảo luận GitHub về nó tại đây .

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

Phần mềm trung gian đó sẽ đọc từ luồng dữ liệu thực tế và lưu trữ nó trong thuộc rawBodytính của yêu cầu. Sau đó, bạn có thể truy cập vào phần thân thô như thế này:

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

Chỉnh sửa: Có vẻ như phương thức này và bodyParser từ chối cùng tồn tại, bởi vì phương thức này sẽ sử dụng luồng yêu cầu trước phương thức kia, dẫn đến bất kỳ phương thức nào sau giây không bao giờ kích hoạt end, do đó không bao giờ gọi next()và treo ứng dụng của bạn.

Giải pháp đơn giản nhất rất có thể sẽ là sửa đổi nguồn của bodyParser, mà bạn sẽ tìm thấy trên dòng 57 của trình phân tích cú pháp JSON của Connect. Đây là những gì phiên bản sửa đổi sẽ trông như thế nào.

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

Bạn sẽ tìm thấy tệp tại vị trí này:

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


Có vẻ như chúng tôi không thể làm điều này. Nếu tôi đã thêm các mã này, các sự kiện trong \ node_modules \ express \ node_modules \ connect \ lib \ middleware \ urlencoded.js sẽ không được kích hoạt. req.on ("data"), req.on ("end") không được kích hoạt .
haitao_wu

Sau khi thêm mã của bạn, tôi xử lý bài đăng của mình bằng cách sử dụng mã này app.post ("/ ajax", function (req, res) {res.send ('hello world, post');}); khi content-type yêu cầu của tôi là application / x-www-form-urlencoded, máy chủ sẽ không phản ứng "hello world, bưu điện"
haitao_wu

vị trí của tập tin là không chính xác trong trường hợp của tôi .. Tôi không có một mô-đun kết nối trong node_modules của nhanh (> 4.0.0) đã không tìm thấy địa điểm mới được nêu ra
Sam Vloeberghs

Kết nối không phải là phần phụ thuộc trong Express 4 và do đó không chứa mô-đun Phân tích cú pháp nội dung. Nếu bạn vẫn cần nó, bạn sẽ tìm thấy nó ở đây .
hexacyanide

1
@hexacyanide Bạn có thể vui lòng cập nhật câu trả lời của mình và bao gồm tham chiếu đến phần mềm trung gian phân tích cú pháp cơ thể mới nhất không? Mô-đun bây giờ bao gồm phần mềm trung gian raw-body-parser . Điều này có thể hữu ích cho những người google đang tìm kiếm một phương pháp để có được phần thân thô.
eAbi

47

Tôi có một giải pháp hoạt động tốt với bodyParser, sử dụng verifycallback trong bodyParser. Trong mã này, tôi đang sử dụng nó để lấy sha1 của nội dung và cũng nhận được phần thân thô.

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

    }
}));

Tôi là người mới trong Node.js và express.js (bắt đầu từ hôm qua, theo nghĩa đen!) Vì vậy tôi muốn nghe ý kiến ​​về giải pháp này.


3
Tôi thực sự thích giải pháp này. Tôi chỉ bao gồm req.rawBody = buf.toString();và loại bỏ phần còn lại của verifychức năng, bởi vì đó là tất cả những gì tôi cần và nó hoạt động rất đẹp. Không cần thay đổi mã nguồn bodyParser!
Greg

+1 nhưng vấn đề của tôi bây giờ là tôi cần một chức năng không đồng bộ để xác minh ướt hơn yêu cầu này đã được gửi trước đó hay chưa: /
Renato Gama

3
rất đẹp. tôi có thể gợi ý khôngreq.rawBody = buf.toString(encoding);
shaharsol

2
Điều này sẽ chụp chỉ application/jsonyêu cầu
Pavel Evstigneev

35

Giải pháp này đã làm việc cho tôi:

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: '*/*' }));

Khi tôi sử dụng giải pháp với req.on('data', function(chunk) { });nó không hoạt động trên phần thân yêu cầu phân đoạn.


Điều này đã xử lý mọi kịch bản chính của dữ liệu đến trong các phần khác nhau của yêu cầu.
Đúng

2
Tôi đã cố gắng xác minh hmac cho một webhook ứng dụng Shopify và điều này đã hiệu quả với tôi. Tôi đại khái đã làm theo ví dụ này: gist.github.com/andjosh/5c4f0244914adfd312e4 .
Chad Johnson

28

Thận trọng với những câu trả lời khác đó vì chúng sẽ không phát đúng với bodyParser nếu bạn đang muốn cũng hỗ trợ json, urlencoded, v.v. Để nó hoạt động với bodyParser, bạn nên điều kiện trình xử lý của mình chỉ đăng ký trên Content-Type(các) tiêu đề bạn nhé. quan tâm đến, giống như bản thân bodyParser.

Để có được nội dung cơ thể thô của một yêu cầu với Content-Type: "text/plain"thành req.rawBodybạn có thể làm:

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. Tôi đã thử một trong các giải pháp ở trên và sau đó tất cả các bài đăng trên GET và json của tôi đều không thành công. Các giải pháp trên đúng về mặt kỹ thuật cho câu hỏi, nhưng nếu bạn đang xử lý các yêu cầu đa dạng hơn với dữ liệu ở nhiều biểu mẫu, bạn sẽ cần điều này.

Dữ liệu ở đây là gì? nó có phải là biến chúng tôi đang gửi từ giao diện người dùng không?
Saras Arya

app.use(bodyParser.urlencoded({limit: '80mb', extended: true})); app.use(bodyParser.json({limit: '80mb'})); app.use(bodyParser.raw({type: 'application/octet-stream'})) Điều này cũng sẽ làm.
Soumya Kanti

15

Đây là một biến thể cho câu trả lời của hexacyanide ở trên. Phần mềm trung gian này cũng xử lý sự kiện 'dữ liệu' nhưng không đợi dữ liệu được tiêu thụ trước khi gọi 'tiếp theo'. Bằng cách này, cả middleware và bodyParser này có thể cùng tồn tại, sử dụng luồng song song.

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
Điều này dường như không hiệu quả với những cơ thể dài, chúng sẽ bị cắt bỏ sớm.
Adam Lockhart

Làm việc hoàn hảo, đã cứu tôi. Cảm ơn bạn.
hakazvaka

Tôi xác nhận rằng điều này cũng hoạt động cho các tệp lớn. Tôi đã thử gửi một tệp văn bản 1,5MB và toàn bộ dữ liệu đã được nhận đúng cách. Cảm ơn bạn
ATOzTOA

@AdamLockhart - yêu cầu của bạn bị cắt giảm ở kích thước nào?
UpTheCreek

@UpTheCreek, đã được một thời gian. Không chắc. Nội dung mới nhất của tôi không sử dụng đoạn mã này, nhưng nếu những người khác báo cáo không có vấn đề gì thì đó có thể là một lỗi đã được sửa.
Adam Lockhart

-1

Sử dụng body-parser Phân tích cú pháp phần body sẽ như thế nào:

app.use(bodyParser.text());

app.use(bodyParser.urlencoded());

app.use(bodyParser.raw());

app.use(bodyParser.json());

I E. Nếu bạn muốn lấy tệp văn bản thô, hãy chạy .text().

Đó là những gì trình phân tích cú pháp cơ thể hiện hỗ trợ

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.