【问题标题】:400 Bad Request issue with POST request from my Vue app to my Rails API从我的 Vue 应用程序到我的 Rails API 的 POST 请求出现 400 Bad Request 问题
【发布时间】:2020-09-21 04:22:41
【问题描述】:

我正在学习 Rails 和 Vue,并创建了一个简单的 Rails API 和 Vue 应用程序来学习如何从我的 Vue 应用程序 GET 和 POST 到我的 Rails API。到目前为止,GET 请求很好,但由于发送 POST 请求的语法错误,我收到了 400 Bad Request。 POST 请求在使用 Insomnia(类似于 Postman 的 API 测试应用程序)对其进行测试时有效,但是当我使用我的 Vue 应用程序进行 POST 时得到400

这是我的 Rails 控制器:

def create
    @todo = Todo.new(todo_params)
    if @todo.save
        render :show, status: :created, location: @todo
    else
        render json: @todo.errors, status: :unprocessable_entity
    end
end

...

private

    def set_todo
        @todo = Todo.find(params[:id])
    end

    def todo_params
        params.require(:todo).permit(:title, :description, :finished)
    end

这是我的 Vue 应用程序,带有一个简单的文本输入以 POST 到我的 Rails:

<template>
<input type="text" v-model="postBody"/>
<button v-on:click="submit()">Submit</button> 
</template>

<script>
import axios from 'axios';
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  data() {
    return {
      todos: [],
      errors: [],
      postBody: ''
    }
  },
methods: {
    submit() {axios.post(`http://localhost:3000/todos/`, { 
        headers: {
          'Content-Type': 'application/json; charset=UTF-8',
        },
        body: JSON.stringify(this.postBody) 
      })
      .then(response => response.data)
      .catch(e => {
        this.errors.push(e)
      })
    }
  }
}
</script>

我尝试将此 POST 请求以 JSON 格式提交到我的 Rails 端点 http://localhost:3000/todos/ 的文本输入中:

{
  "title": "Sweets",
  "description": "Buy cookies",
  "finished": false
}

然后我从浏览器收到此错误:

{status: 400, error: "Bad Request",…}
error: "Bad Request"
exception: "#<ActionController::ParameterMissing: param is missing or the value is empty: todo>"
status: 400
traces: {Application Trace: [{id: 1, trace: "app/controllers/todos_controller.rb:51:in `todo_params'"},…],…}
Application Trace: [{id: 1, trace: "app/controllers/todos_controller.rb:51:in `todo_params'"},…]
0: {id: 1, trace: "app/controllers/todos_controller.rb:51:in `todo_params'"}
1: {id: 2, trace: "app/controllers/todos_controller.rb:24:in `create'"}

这是我从本地 Rails 服务器的终端收到的错误(我正在 Vue 和 Rails 的本地环境中测试):

Started POST "/todos/" for ::1 at 2020-09-21 12:09:16 +0800
Processing by TodosController#create as JSON
  Parameters: {"headers"=>{"Content-Type"=>"application/json; charset=UTF-8"}, "body"=>"\"{   \\\"title\\\": \\\"Sweets\\\", \\t\\\"description\\\": \\\"Buy cookies\\\",   \\\"finished\\\": false }\"", "todo"=>{}}
Completed 400 Bad Request in 0ms (ActiveRecord: 0.0ms)
  
ActionController::ParameterMissing (param is missing or the value is empty: todo):
  
app/controllers/todos_controller.rb:51:in `todo_params'
app/controllers/todos_controller.rb:24:in `create'

我知道这可能与我的 Rails 控制器中的强参数有关,所以当我删除所需的参数 .require(:todo) 时,POST 会通过,但 JSON 字段都是空的。

  {
    "id": 6,
    "title": null,
    "description": null,
    "finished": null
  }

我还尝试查看它是否与我的 Vue 应用程序中的表单数据如何发送到我的 Rails 端点有关,所以我在body 上尝试了JSON.stringify,但没有帮助。

这是我试图解决这个问题的第 3 天,但没有成功。我做错什么了?非常感谢任何帮助! :)

【问题讨论】:

  • API 测试应用程序添加缺失的信息,纠正格式错误的 JSON 以帮助开发人员。当然,您正在构建的实际应用程序不会这样做。如果有帮助,我会尝试使用一些现成的代码或获取 API,或者一些现成的 API 消费库,看看问题出在哪里。
  • @Jay 对不起,我是 Rails 和 Vue 的新手,所以我要问一个菜鸟问题:我应该如何使用现成的代码和/或 API 消费库来解决这个问题?一些粗略的步骤对我进一步研究非常有帮助! :)
  • 如果我是你,我会浏览 Vue 文档和教程网站,了解其他人是如何进行 API 调用的。我在 node 和 .NET 上工作,并且都准备好使用库来做到这一点。我不使用 Vue,但 React 只是使用 JavaScript 获取。所以,真的,你只需要花一些时间阅读 Vue 官方文档
  • 你试过 params.permit(:todo)
  • @SRDP 是的,我做到了,它可以发送 POST,但 json 字段都是空的

标签: javascript ruby-on-rails ruby vue.js vuejs2


【解决方案1】:

首先,您在 JSON 有效负载的根目录上提交 titledescription 等,但 Rails 期望它们嵌套在 todo 下。

其次,您在 axios 请求的有效负载参数中提交标头 - post 的第一个参数是有效负载,第二个参数是配置。

第三,您应该不需要将数据转换为 JSON 字符串。 axios 应该会为您处理。

试试这个 axios 请求:

axios.post(
  `http://localhost:3000/todos/`,
  { todo: this.postBody },
  { headers: { 'Content-Type': 'application/json; charset=UTF-8' }
)

【讨论】:

  • 感谢@Tim Krins!我试过你的代码,post 各种版本的 json,得到 500 Internal Server Error ......我迷路了。 NoMethodError (undefined method permit' for #<0x00007fb8e91bd920>
【解决方案2】:

在从 Rails 控制台发现各种错误消息的兔子洞之后,我意识到这与 Rails API 或强参数无关,而是我如何将输入构造为不是 POST 到我的 Rails 端点的格式错误的 JSON .阅读 npm axios 文档有助于加载。

因此,我在 Vue 应用程序中创建了一个字段名称与我的参数匹配的表单,而不是单个文本输入字段:

<form @submit.prevent="onSubmit">
  <div class="input">
    <label for="title">Title</label>
    <input
       type="text"
       id="title"
       v-model="title">
  </div>
  <div class="input">
    <label for="name">Description</label>
    <input
      type="text"
      id="description"
      v-model="description">
  </div>
  <div class="input">
    <label for="finished">Finished?</label>
    <input
      type="text"
      id="finished"
      v-model="finished">
  </div>
  <div class="submit">
    <button type="submit">Submit</button>
  </div>
</form>

然后在我的方法中:

methods: {
    onSubmit() {
      const formData = {
      title: this.title,
      description: this.description,
      finished: this.finished      
      }
      axios({
        method: "POST",
        url: "http://localhost:3000/todos/",
        headers: {"Content-Type": "application/json"},
        data: formData
      })
      .then(response => { 
        console.log(response);
      })
      .catch(e => {
      this.errors.push(e)
      })
    },

这就成功了!我现在可以 POST 到我的 Rails API。对我来说问题是我仍然不明白它是如何以及为什么起作用的,除了它!因此,任何答案都只对个人学习表示赞赏(但对原始问题并不重要)。

【讨论】:

    猜你喜欢
    • 2016-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多