【问题标题】:jQuery AJAX JSONP Returns 400 Bad RequestjQuery AJAX JSONP 返回 400 错误请求
【发布时间】:2020-04-23 01:38:10
【问题描述】:

我正在尝试使用 jQuery AJAX 将字符串化的 JSON 发送到本地地址。

此地址正在等待接收 JSON 数据。

但是,一旦发送,它就会返回“400 Bad Request”。

//response received as: {"success":"true","packages":["https://example.com/link1.pkg","https://example.com/link2.pkg","https://example.com/link3.pkg"]}

var res = JSON.parse(response); 
var packages = [];

$.each(res.packages, function (i, item) { // put links in array
    packages.push(item);
});

if (res.success) {
    $.ajax({
        url: 'http://192.168.2.10:12800/api/install',
        type: 'POST',
        headers: {
            'Access-Control-Allow-Origin': '*', // cors
            'Content-Type': 'application/json'
        },
        contentType: 'application/json; charset=utf-8',
        dataType: 'jsonp',
        data: JSON.stringify({
            'type': 'direct',
            'packages': packages
        }),
        success: function (response) {
            $('#dynamicModal').find('#response').html('<p>Packages sent!</p>');
        },
        error: function (response) {
            $('#dynamicModal').find('#response').html('<p>Error occurred while sending.</p>');
        }
    });
} else {
    $('#dynamicModal').find('#response').html('<p>Error occurred while gathering links.</p>');
}

我在 Google 上检查了很多链接,90% 的人说 JSON 没有被字符串化,但我的是。我没有想法,我希望有人可以帮助我并可能看到这个问题。

这是完整的控制台错误:

GET http://192.168.2.10:12800/api/install?callback=jQuery3410603622444131205_1578188027542&{%22type%22:%22direct%22,%22packages%22:[%22http://example.com/EXAMPLE_0.pkg%22,%22http://example.com/EXAMPLE_1.pkg%22,%22http://example.com/EXAMPLE_2.pkg%22,%22http://example.com/EXAMPLE_3.pkg%22,%22http://example.com/EXAMPLE_4.pkg%22,%22http://example.com/EXAMPLE_5.pkg%22,%22http://example.com/EXAMPLE_6.pkg%22]}&_=1578188027543 net::ERR_ABORTED 400 (Bad request)

更新

我在本地服务器上找到了失败的代码:

static int event_handler(sb_Event* e) {
    const struct handler_desc* descs = NULL;
    handler_cb* handler = NULL;
    char* in_data;
    size_t in_size;
    size_t count;
    size_t i;
    int ret;

    if (e->type != SB_EV_REQUEST) {
        ret = SB_RES_OK;
        goto done;
    }

    if (strcasecmp(e->method, "GET") == 0) {
        descs = s_get_handlers;
        count = ARRAY_SIZE(s_get_handlers);
    } else if (strcasecmp(e->method, "POST") == 0) {
        descs = s_post_handlers;
        count = ARRAY_SIZE(s_post_handlers);
    }
    if (!descs) {
bad_request:
        kick_error(e->stream, 400, "Bad request", "Unsupported method");
        ret = SB_RES_OK;
        goto done;
    }

    for (i = 0; i < count; ++i) {
        if (descs[i].need_partial_match) {
            if (strstr(e->path, descs[i].path) == e->path) {
                handler = descs[i].handler;
                break;
            }
        } else {
            if (strcmp(e->path, descs[i].path) == 0) {
                handler = descs[i].handler;
                break;
            }
        }
    }
    if (!handler) {
        goto bad_request;
    }

    in_data = sb_get_content_data(e->stream, &in_size);

    (*handler)(e->stream, e->method, e->path, in_data, in_size);

    ret = SB_RES_OK;

done:
    return ret;
}

在我看来,这似乎无法获得 s_get_handlerss_post_handlers

【问题讨论】:

  • 通常您不会对data 字段进行字符串化,您是否尝试过为该字段提供原始 json 对象?您是否还注意到您指定了 POST 但控制台错误显示 GET?看起来服务器端可能只希望处理带有 GET 请求的 URL。
  • @NathanHawks 我已经取消了 data 字段的字符串化并将 POST 更改为 GET 但结果没有更改。 GET可以是返回结果吗?
  • 不,返回结果既不是POST也不是GET。好的,所以我不建议您将 AJAX 请求更改为 GET。相反,我认为您应该在服务器端找到需要 GET 的代码,并将 that 更改为 POST。无论发生什么,400 表示您发送了一个畸形的请求。归结为:您发送的 var 不是预期的,或者缺少 var,或者方法 (GET/POST) 错误。
  • @NathanHawks 你好 Nathan,我已经添加了失败的服务器的相关代码。
  • 你的客户端代码全是废话,不能发出POST请求or用JSON的时候设置请求头,可以设置请求头的时候, Access-Control-Allow-Origin 不是其中之一:它是一个 response 标头。

标签: javascript jquery ajax http-status-code-400


【解决方案1】:

最可能的解决方案:将 processData: false 添加到您的参数中,这应该会使传递给数据的字符串不被处理,并且应该作为 POST 原始正文发送:

if (res.success) {
  $.ajax({
    url: 'http://192.168.2.10:12800/api/install',
    ...
    processData: false,
    data: JSON.stringify({
    ...

但只要我知道您不能发送 JSONP POST 请求,因为 JSONP 请求是如何产生的:使用动态创建的标签。这些请求将始终是 GET 请求,因此您不能发送原始正文。在您的开发者网络选项卡上检查它(见下)。如果要发送 POST 请求,则必须使用非 JSONP 请求并在 192.168.2.10:12800 服务器上正确设置 CORS。这是在该服务器上设置的响应标头 Access-Control-Allow-Origin: http://siteA.com 其中 siteA.com 是调用者页面所在的域。查看更多关于How does Access-Control-Allow-Origin header work?

不得不提一下可能JQuery使用了一个技巧,但是我认为JSONP不兼容发送POST请求,因为是通过创建标签来请求的。

您可以使用浏览器中开发人员栏中的网络选项卡检查此解决方案以及其他解决方案的请求更改方式(您知道,使用 F12 打开)。例如激活 processData: false 应该改变 url 和请求正文。

不太可能的解决方案:更改数据以指定至少一个参数,具体取决于您的 API,因此字符串化的数据将在一个命名参数下发送,该参数尊重最常用的标准化协议:/ /host/path/resource?param=value&param=value&param=value url 格式。

例如,如果您想在名为 json 的参数下发送数据,您应该使用:

if (res.success) {
  $.ajax({
    url: 'http://192.168.2.10:12800/api/install',
    ...
    data: {
      json: JSON.stringify({
        'type': 'direct',
        'packages': packages
      })
    },
    ...

原因:如果您从错误中分析您的 URL,请将其拆分为多个部分:

http://192.168.2.10:12800/api/install

第一个参数:

?callback=jQuery3410603622444131205_1578188027542

秒(格式错误,没有参数名称):

&{%22type%22:%22direct%22,%22packages%22:[%22http://example.com/EXAMPLE_0.pkg%22,%22http://example.com/EXAMPLE_1.pkg%22,%22http://example.com/EXAMPLE_2.pkg%22,%22http://example.com/EXAMPLE_3.pkg%22,%22http://example.com/EXAMPLE_4.pkg%22,%22http://example.com/EXAMPLE_5.pkg%22,%22http://example.com/EXAMPLE_6.pkg%22]}

最后的论点:

&_=1578188027543

第一个是JQuery动态回调,最后一个是反缓存,看起来还可以,但第二部分似乎格式错误。当然你可以使用自己的 url 方案,但标准的不使用没有参数名称的 json 数据形式。因此,您可能想在 POST 原始正文中发送 json 数据,或者发送一个将 json 字符串化为值的命名参数。

相关问题:Send POST data via raw json with postmanAlways failed when POST data with json (body: raw)

【讨论】:

  • 我已经尝试过你的两个 sn-ps,但遗憾的是它们似乎并没有解决问题。然而,发送未字符串化的数据似乎可以解决 JSON-in-URL 问题。我开始怀疑是否可以从网络服务器 ping 本地服务器...
  • 如果您从 https 上下文加载 http(不安全)资源,但不是因为 ips 或地址,可能会失败。无论如何,问题将显示在开发人员工具的网络选项卡中。
  • 嗯...我重新阅读了自己的答案...也许我没有充分解释 processData: false 影响...激活此选项应该使数据在 POST 中直接发送正文,所以它应该从网址本身消失。但是,这取决于您的 API:不同的 API 旨在接收不同类型的请求。
  • 你好,我意识到用JSONP方法发出POST请求没有任何意义,而且除了JQUery有新技巧外,应该不可能。所以你不能同时使用 JSONP 和 POST。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-02
  • 1970-01-01
  • 1970-01-01
  • 2011-07-11
  • 2014-07-06
  • 1970-01-01
  • 2019-07-28
相关资源
最近更新 更多