簡體   English   中英

從我的 Vue 應用程序到我的 Rails API POST 請求的 400 Bad Request 問題

[英]400 Bad Request issue with POST request from my Vue app to my Rails API

我正在學習 Rails 和 Vue,並創建了一個簡單的 Rails API 和 Vue 應用程序來學習如何從我的 Vue 應用程序 GET 和 POST 到我的 Rails API。 到目前為止,GET 請求很好,但由於發送 POST 請求的語法錯誤,我收到了 400 個錯誤的請求。 使用 Insomnia(類似於 Postman 的 API 測試應用程序)對其進行測試時,POST 請求有效,但是當我使用我的 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 天,但沒有成功。 我做錯了什么? 非常感謝任何幫助! :)

首先,您在 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' }
)

在從 Rails 控制台深入了解各種錯誤消息后,我意識到這與 Rails API 或強參數無關,而是我如何構建輸入以不將格式錯誤的 JSON POST到我的 Rails 端點。 閱讀 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。 對我來說的問題是我仍然不明白它是如何以及為什么起作用的,除了它! 因此,任何答案都只為個人學習而受到贊賞(但對原始問題並不重要)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM