突发application/x-www-form-urlencoded不支持错误,Elixir后端咨询
让我们一步步拆解你的问题,找出根源和解决方案:
问题根源分析
首先看你的错误日志和配置:
21:28:14.345 [debug] ** (Plug.Parsers.UnsupportedMediaTypeError) unsupported media type application/x-www-form-urlencoded
你的Elixir后端配置里,Plug.Parsers只启用了:json解析器,并且限定只接受application/json类型:
plug Plug.Parsers, parsers: [:json], pass: ["application/json"], json_decoder: Poison
而你的前端请求实际发送的Content-Type是application/x-www-form-urlencoded,这和后端的预期完全不匹配,所以触发了415错误。
再看你的前端代码,发现了关键问题:你写的请求头是{ 'Content-': 'application/json' }——这里的键名少了Type!应该是'Content-Type'。这个笔误导致浏览器没有收到正确的Content-Type指令,自动用了默认的表单编码格式发送数据,这就是“突然报错”的核心原因(之前正常的时候应该是正确设置了这个请求头)。
你的疑问逐一解答
1. 为什么之前正常现在突然报错?
几乎可以肯定是前端代码的请求头配置被误改了。之前正常时,你应该是正确设置了Content-Type: application/json,并且请求体是JSON格式,和后端的配置匹配。现在因为键名写错,浏览器 fallback 到默认的application/x-www-form-urlencoded编码,导致后端拒绝接收。
2. application/x-www-form-urlencoded存在弊端吗?
是的,它在现代API场景下有不少局限:
- 不支持复杂数据结构:只能传递扁平的键值对,嵌套对象、数组这类复杂数据需要手动编码,非常繁琐。
- 可读性和扩展性差:编码后的格式不如JSON直观,后续扩展接口传递复杂数据时会非常麻烦。
- 不符合RESTful规范:JSON是当前RESTful API的通用数据格式,几乎所有后端框架对JSON的支持都更完善、更高效。
3. 最优解决方案:修正前端代码(推荐)
最优方案是修复前端的请求配置,而不是修改后端。原因很简单:你的后端已经遵循了现代API的最佳实践,没必要为了一个笔误兼容旧格式,而且前端修正的成本极低。
具体修正步骤:
- 修复请求头键名:把
'Content-'改成'Content-Type',确保值为'application/json'。 - 显式转换请求体为JSON字符串:确保发送的是JSON格式的内容,而不是表单对象。
- 优化参数传递:你现在同时在URL查询参数和请求体里传递了
p_id和s_id,可以二选一(PUT请求通常把数据放在请求体里更符合规范)。
修正后的代码示例:
import { ajax } from 'rxjs/observable/dom/ajax' import { Observable } from 'rxjs/Observable' return ajax({ body: JSON.stringify(action.payload), method: 'PUT', headers: { 'Content-Type': 'application/json' }, url: `http://192.168.20.6:4000/products/` }).map(response => updateEditProductInDbFulfilled(response)) .catch(error => Observable.of(updateEditProductInDbRejected(error)))
备选方案:修改后端支持表单编码
如果确实需要兼容其他发送表单编码的客户端,也可以修改后端的Plug.Parsers配置,添加:urlencoded解析器:
plug Plug.Parsers, parsers: [:urlencoded, :json], pass: ["application/x-www-form-urlencoded", "application/json"], json_decoder: Poison
但还是优先推荐使用JSON格式,它更适合长期维护和扩展。
内容的提问来源于stack exchange,提问作者BeniaminoBaggins

