请教个关于Nodejs中Request Payload的问题

请教个关于Nodejs中Request Payload的问题

做项目要更新redmine的状态,一直不成功,贴出代码,求各位大神指导!

var hex = ‘zEpLAwrPVTS47stg’;

(var contents = getPayload([
{name: '_method', value: 'put'},

{name: ‘issue[subject]’, value: ‘标题’}, {name: ‘done_ratio’, value: ‘55’}, {name: ‘commit’, value: ‘提交’} ], hex);

var options = { host: this.host, port: this.port, path: ‘/redmine/issues/2223’, method: ‘post’, headers: { ‘Content-Length’: + contents.length, ‘Content-Type’: ‘multipart/form-data; boundary=----WebKitFormBoundar’ + hex, ‘Cookie’: session } };

send(options, contents, function (header, data) { console.log(data); });)();

function send(option, data, callback) { var req = http.request(option, function(res) { var resData = ‘’;

res.setEncoding(‘utf8’);

res.on(‘data’, function (chunk) { resData += chunk; });

res.on(‘end’, function () { callback && callback(res.headers, resData); }); });

data && req.write(data); req.end(); }

function getPayload(array, hex) { var data = ‘’;

array.forEach(function (elm, index) { data += (’------WebKitFormBoundary’ + hex + ‘\r\n’ + ‘Content-Disposition: form-data; name="’ + elm.name + ‘"’ + ‘\r\n\r\n’ + elm.value + ‘\r\n’); });

data += (’------WebKitFormBoundary’ + hex);

return data; }


2 回复

好的,让我们来解答这个问题。你遇到的问题可能是由于 Content-Typerequest payload 的格式不正确导致的。在发送 POST 请求时,确保 Content-Type 和请求体的数据格式一致非常重要。

问题分析

  1. Content-Type 设置错误:你的代码中 Content-Type 设置为 multipart/form-data,但是没有正确地生成 multipart 数据。
  2. 边界符使用错误Content-Type 中使用的边界符需要在数据中正确地使用。

解决方案

我们需要正确地构建一个 multipart/form-data 请求体,并且确保 Content-Type 和请求体中的数据格式一致。

示例代码

const http = require('http');

// 生成请求体
function getPayload(array, hex) {
    let data = '';

    array.forEach(function (elm) {
        data += ('------WebKitFormBoundary' + hex + '\r\n');
        data += ('Content-Disposition: form-data; name="' + elm.name + '"\r\n\r\n');
        data += (elm.value + '\r\n');
    });

    data += ('------WebKitFormBoundary' + hex + '--');

    return data;
}

// 发送请求
function send(options, data, callback) {
    const req = http.request(options, function (res) {
        let resData = '';
        res.setEncoding('utf8');

        res.on('data', function (chunk) {
            resData += chunk;
        });

        res.on('end', function () {
            callback(res.headers, resData);
        });
    });

    if (data) {
        req.write(data);
    }

    req.end();
}

// 主函数
function updateRedmineIssue() {
    var hex = 'zEpLAwrPVTS47stg';
    var contents = getPayload([
        {name: '_method', value: 'put'},
        {name: 'issue[subject]', value: '标题'},
        {name: 'done_ratio', value: '55'},
        {name: 'commit', value: '提交'}
    ], hex);

    var options = {
        host: 'your.redmine.host',
        port: 80,
        path: '/redmine/issues/2223',
        method: 'POST',
        headers: {
            'Content-Length': Buffer.byteLength(contents),
            'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundary' + hex,
            'Cookie': 'your-session-cookie'
        }
    };

    send(options, contents, function (header, data) {
        console.log(data);
    });
}

updateRedmineIssue();

关键点解释

  1. getPayload 函数:生成了正确的 multipart/form-data 格式的数据。
  2. Content-Type 设置:确保与请求体中的数据格式一致。
  3. Content-Length 设置:根据实际请求体的长度动态设置。

通过以上修改,应该可以解决你遇到的问题。如果还有其他问题,请继续提供更多信息。


根据你的描述,你的问题主要涉及如何构建正确的请求体(Request Payload)来更新 Redmine 中的 Issue 状态。当前代码中有一些问题需要修正,比如 Content-Type 的定义、生成边界字符串的方式以及请求体的格式。

以下是修正后的代码示例:

修改后的 getPayload 函数

function getPayload(array, hex) {
    var boundary = '----WebKitFormBoundary' + hex;
    var data = '';

    array.forEach(function (elm, index) {
        data += (
            boundary + '\r\n' +
            'Content-Disposition: form-data; name="' + elm.name + '"\r\n' +
            '\r\n' +
            elm.value + '\r\n'
        );
    });

    data += (boundary + '--');

    return data;
}

修改后的 options 对象

确保 Content-Type 的定义是正确的,并且不要忘记在 Content-Length 前加上正确的单位。

var options = {
    host: this.host,
    port: this.port,
    path: '/redmine/issues/2223',
    method: 'POST',
    headers: {
        'Content-Length': Buffer.byteLength(contents, 'utf8'),
        'Content-Type': 'multipart/form-data; boundary=' + boundary,
        'Cookie': session
    }
};

调用 getPayload 函数

确保 hex 是一个随机生成的字符串,以确保每次请求时边界不同。

var hex = require('crypto').randomBytes(16).toString('hex');
var contents = getPayload([
    { name: '_method', value: 'put' },
    { name: 'issue[subject]', value: '新标题' },
    { name: 'done_ratio', value: '55' },
    { name: 'commit', value: '提交' }
], hex);

// 创建请求
var req = http.request(options, function (res) {
    let resData = '';
    res.setEncoding('utf8');
    res.on('data', function (chunk) {
        resData += chunk;
    });
    res.on('end', function () {
        console.log(resData);
    });
});

// 写入请求体
req.write(contents);
req.end();

总结

上述代码修正了 Content-TypeContent-Length 的设置,并且正确地构建了多部分表单数据。这样可以确保你的请求能够被 Redmine 正确解析。希望这可以帮助你解决遇到的问题。如果仍然有问题,请检查 Redmine 的 API 文档,确认是否需要其他额外的头信息或数据字段。

回到顶部