记录Ajax请求报415与404问题

问题描述与分析

今天帮同学旁边同事解决了一个问题,问题是这样的:我们有一个前后端未分离的项目agentBuyFreemark+JQuery),同事想本地启动agentBuy MVC服务(http:localhost:8001),联调后端同事的本地启动的web-inquiry服务(http://127.168.24.68:9366),直接联调会有跨域问题,于是同事本地启动网关服务webagentagentBuyweb-inquiry服务代理到http:webagent.java.com:10000域名下联调,但是发现接口报了415

// agentBuy  
var params = {
  "storeId":"HL000001",
  "quoteType":"AUTO",
  "enable":"Y"
};
$.ajax({
  url: WEB_ROOT + '/inquiryWeb/supply/quote/enable', // 在本地为http:webagent.java.com:10000/inquiryWeb/supply/quote/enable
  type: 'post',
  data : params,
  dataType: 'json',
  success: function (response) {
    // code...
  }
})

发现请求的入参会转化成键值对的形式,Request Payload

storeId=HL000001&quoteType=AUTO&enable=Y

响应状态码为415(Unsupported Media Type),表示服务器无法处理请求附带的媒体格式 (不支持的媒体类型)

@Log4j2
@RestController
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class SupplyQuotationConfigController {

  private final SupplyQuotationConfigClient supplyQuotationConfigClient;

  private static final String REQUEST_NOT_VALIDATE = "请求参数校验不通过~";
  private static final String INTERNAL_SERVER_ERROR = "网络异常,请稍后重试~";

  @PostMapping("/supply/quote/enable")
  public ResponseEntity<Result<Boolean>> setSupplyQuoteEnable(@RequestBody SupplyQuoteEnableRequest request) {
    if (null == request || !request.validate()){
      return new ResponseEntity<>(new Result<>(HttpStatus.BAD_REQUEST.value(), REQUEST_NOT_VALIDATE, Boolean.FALSE), HttpStatus.OK);
    }
    try {
      supplyQuotationConfigClient.setSupplyQuoteEnable(SupplyQuotationConfigFactory.toSupplyQuotationEnableRequest(request));
      return new ResponseEntity<>(new Result<>(HttpStatus.OK.value(), null, Boolean.TRUE), HttpStatus.OK);
    }catch (HttpMessageException e){
      return new ResponseEntity<>(new Result<>(e.getStatusCode(), e.getMessage(), Boolean.FALSE), HttpStatus.OK);
    }catch (Exception e){
      return new ResponseEntity<>(new Result<>(HttpStatus.INTERNAL_SERVER_ERROR.value(), INTERNAL_SERVER_ERROR, Boolean.FALSE), HttpStatus.OK);
    }
  }
}

在排查后端接口发现,请求参数使用了@RequestBody注解,用来接收前端传递给后端的json字符串数据,而现在传的键值对的类型,因为如果没有自行指定request header Content-Type,默认为application/x-www-form-urlencoded,因此前后端定义的参数类型不一致,从而报了415错误。

request header中设置Content-Type:application/json就可以解决415问题,但是重新请求却报了404,我仔仔细细对照了一遍请求路径,发现并没有什么问题,并且使用postman本地调试接口也没有问题,百思不得其解。

后面发现request header中设置了Content-Type:application/json,但Request Payload还是为键值对:

storeId=HL000001&quoteType=AUTO&enable=Y

难道是因为键值对参数会追加在URL后面使得请求路径不对?这是为何会变成键值对呢?

因为在没有 MIME 类型的情况下,或者在某些浏览器认为设置的MIME 类型不正确情况下,浏览器可能会执行MIME 嗅探,通过查看资源的字节来猜测正确的 MIME 类型。上面我们设置Content-Type:application/jsonapplication/json表示需要传一个json字符串,但是我们传的是json数据,浏览器认为设置的MIME 类型不正确,将参数判定成了键值对形式,因此才导致后续请求报404

我们只需要将入参改成json字符串即可解决该问题:

// agentBuy  
var params = {
  "storeId":"HL000001",
  "quoteType":"AUTO",
  "enable":"Y"
};
$.ajax({
  url: WEB_ROOT + '/inquiryWeb/supply/quote/enable', // 在本地为http:webagent.java.com:10000/inquiryWeb/supply/quote/enable
  type: 'post',
  data : JSON.stringify(params), // 改成json字符串
  dataType: 'json',
  success: function (response) {
    // code...
  }
})

参考:

ajax post请求报错415或400解决方案

MIME 嗅探

https://developer.mozilla.org...

avatar
记得要微笑
前端工程师

求上而得中,求中而得下,求下而不得

1.7k 声望
4.4k 粉丝
0 条评论
推荐阅读
alicdn边缘节点不稳定导致页面崩溃问题
某工作日,线上某用户向客服专员反馈没法正常访问“查看报价页面”,页面内容没有呈现。客服专员收到反馈后,将问题转交给SRE处理。很奇怪的是,SRE访问生产环境“查看报价页面”显示正常,为了进一步分析定位问题,S...

记得要微笑阅读 734

再也不学AJAX了!(三)跨域获取资源 ① - 同源策略
「再也不学 AJAX 了」是一个以 AJAX 为主题的系列文章,希望读者通过阅读本系列文章,能够对 AJAX 技术有更加深入的认识和理解,从此能够再也不用专门学习 AJAX。本篇文章为该系列的第四篇,最近更新于 2023 年 1...

libinfs19阅读 4k评论 4

封面图
再也不学 AJAX 了!(一)AJAX 概述
跨域获取数据:介绍了与「跨域发送 AJAX 请求」相关的一些内容:例如「同源策略」与四种跨域请求资源的方式:JSONP,CORS,postMessage 和 WebSocket;

libinfs19阅读 3.9k评论 6

封面图
再也不学AJAX了!(二)使用AJAX ② Fetch API
「再也不学 AJAX 了」是一个以 AJAX 为主题的系列文章,希望读者通过阅读本系列文章,能够对 AJAX 技术有更加深入的认识和理解,从此能够再也不用专门学习 AJAX。本篇文章为该系列的第三篇,最近更新于 2023 年 1...

libinfs2阅读 609

封面图
Ajax实现搜索联想 搜索关键词提醒 无刷新搜索
通过javascript监听搜索框的内容,调用后端即可。(1)javascript监听搜索框的内容(2)把搜索框的关键词传给后端进行搜索(3)搜索到结果,遍历到页面

TANKING1阅读 4.4k

Y 分钟速成 jquery
jQuery是JavaScript的一个函数库,它可以帮你“写更少,做更多”。它集成了很多常见的JavaScript任务并且很容易调用。jQuery被世界各地的很多的大公司和开发者使用。它包括了AJAX,事件处理,文档操作以及很多其它...

小X学技术阅读 692

nginx反向代理POST请求
nginx反向代理POST请求在使用nginx反向代理POST请求的时候,错误配置情况 {代码...} 这样配置会出现的问题原本发出的请求是POST请求,经过nginx转发以后就会变成GET请求原本POST请求携带的请求体经过转发以后会丢...

是洋不是阳阅读 608

avatar
记得要微笑
前端工程师

求上而得中,求中而得下,求下而不得

1.7k 声望
4.4k 粉丝
宣传栏