乐趣区

关于ajax:记录Ajax请求报415与404问题

问题形容与剖析

明天帮同学旁边共事解决了一个问题,问题是这样的:咱们有一个前后端未分离的我的项目 agentBuyFreemark+JQuery),共事想本地启动agentBuy 服务(http:localhost:8001),联调后端共事的本地 web-inquiry 服务(http://127.168.24.68:9366),间接联调会有跨域问题,于是共事本地启动网关服务(spring cloud gateway)将 agentBuyweb-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…

退出移动版