Go的HTTP Post请求在Ruby On Rails API中没有正确格式化数据。

huangapple go评论87阅读模式
英文:

Go HTTP Post Request not formatting data properly for Ruby On Rails API

问题

我已经用中文翻译了你的内容,请查看以下翻译结果:

我已经在Go中构建了一个客户端,用于与我的Rails API进行交互。我有一个名为bar的模型,其中有一个名为test的字符串属性。我试图循环遍历一系列字符串,这些字符串是test属性的值,并向我的API发送POST请求。

这是我的Go客户端的代码:

for _, data := range attributes {
    client := new(http.Client)

    body := []byte(fmt.Sprintf("bar: {test: %s}", data))
    fmt.Println(string(body))

    req, err := http.NewRequest(
        "POST",
        "http://localhost:3000/bars.json",
        bytes.NewReader(body),
    )

在我的Rails服务器后端,我得到了以下错误:

ActionController::ParameterMissing (param is missing or the value is empty: bar):
  
app/controllers/bars_controller.rb:70:in `bar_params'
app/controllers/bars_controller.rb:25:in `create'
Invalid or incomplete POST params

我尝试了几种不同的方式来格式化我的Go请求,但似乎没有任何一种方式与API正常工作。我应该如何正确格式化我的POST请求数据?

*** 更新 ***

设置请求头的内容类型并使用json.Marshal确实是朝着正确方向迈出的一步,但现在我遇到了一个新的错误。以下是我目前的代码:

for _, data := range attributes {
    client := new(http.Client)
    
    d := fmt.Sprintf("{test: %s}", data)
    b, err := json.Marshal(map[string]string{"bar": d})

    body := []byte(string(b))
    fmt.Println(string(body))

    req, err := http.NewRequest(
        "POST",
        "http://localhost:3000/bars.json",
        bytes.NewReader(body),
    )

    req.Header.Set("Content-Type", "application/json; charset=UTF-8")

    resp, err := client.Do(req)

这是我的Rails API的代码:

class BarsController < ActionController::API
    # POST /bars or /bars.json
  def create
    @bar = Bar.new(bar_params)

    if @bar.save
      render :show, status: :created, location: @bar 
    else
      render json: @bar.errors, status: :unprocessable_entity 
    end
  end

   private 
    def bar_params
      params.require(:bar).permit(:test)
    end
end

服务器端错误:

Started POST "/bars.json" for ::1 at 2022-07-19 10:36:12 -0400
Processing by BarsController#create as JSON
  Parameters: {"bar"=>"{test: test}"}
Completed 500 Internal Server Error in 0ms (ActiveRecord: 0.0ms | Allocations: 426)

  
ArgumentError (When assigning attributes, you must pass a hash as an argument, String passed.):
  
app/controllers/bars_controller.rb:24:in `create'

是否有其他的方法来格式化我的请求数据,以便Rails API将其识别为哈希值?

英文:

I've built a client in Go to interact with my Rails API. I have a model bar with a single string attribute of test. I'm trying to loop through a series of strings which are the values for the test attribute and send POST request to my API.

Here is the code for my Go client:

for _,data := range attributes{
    client := new(http.Client)

    body := []byte(fmt.Sprintf(&quot;bar: {test: %s}&quot;, data))
    fmt.Println(string(body))

    req, err := http.NewRequest(
      &quot;POST&quot;,
      &quot;http://localhost:3000/bars.json&quot;,
      bytes.NewReader(body),
    )

On the backend of my Rails server here is the error that I am getting:

ActionController::ParameterMissing (param is missing or the value is empty: bar):
  
app/controllers/bars_controller.rb:70:in `bar_params&#39;
app/controllers/bars_controller.rb:25:in `create&#39;
Invalid or incomplete POST params

I've tried formatting my Go request a couple different ways but nothing seems to work properly with the API. How do I format the data for my post request correctly?

*** UPDATE ***

Setting the request header content type and using json.Marshal was definitely a step in the right direction, however I am now running into a new error. Here is what my code looks like so far:

for _,data := range attributes{
    client := new(http.Client)
    
     d := fmt.Sprintf(&quot;{test: %s}&quot;, data)
     b, err := json.Marshal(map[string]string{&quot;bar&quot;: d})

    body := []byte(string(b))
    fmt.Println(string(body))

    req, err := http.NewRequest(
      &quot;POST&quot;,
      &quot;http://localhost:3000/bars.json&quot;,
      bytes.NewReader(body),
    )

    req.Header.Set(&quot;Content-Type&quot;, &quot;application/json; charset=UTF-8&quot;)

    resp,err := client.Do(req)

And here is the Code for my Rails API:

class BarsController &lt; ActionController::API
    # POST /bars or /bars.json
  def create
    @bar = Bar.new(bar_params)

    if @bar.save
      render :show, status: :created, location: @bar 
    else
      render json: @bar.errors, status: :unprocessable_entity 
    end
  end

   private 
    def bar_params
      params.require(:bar).permit(:test)
    end
end

The Server side error:

Started POST &quot;/bars.json&quot; for ::1 at 2022-07-19 10:36:12 -0400
Processing by BarsController#create as JSON
  Parameters: {&quot;bar&quot;=&gt;&quot;{test: test}&quot;}
Completed 500 Internal Server Error in 0ms (ActiveRecord: 0.0ms | Allocations: 426)

  
ArgumentError (When assigning attributes, you must pass a hash as an argument, String passed.):
  
app/controllers/bars_controller.rb:24:in `create&#39;

Is there an alternative way to format my request data so that the Rails API recognizes it as a hash?

答案1

得分: 1

  1. 这个"bar: {test: %s}"不是一个有效的 JSON 格式,请尝试使用"{ \"bar\": {\"test\": \"%s\"} }"(注意引号和括号),最好使用json.Marshal进行处理。
  2. 添加 JSON 内容类型头部 req.Header.Set("Content-Type", "application/json; charset=UTF-8")
英文:
  1. That's &quot;bar: {test: %s}&quot; not a valid json, try &quot;{ &quot;bar&quot;: {&quot;test&quot;: &quot;%s&quot;} }&quot; (notice quotes and brackets), its better to use json.Marshal.
  2. Add json content type header req.Header.Set(&quot;Content-Type&quot;, &quot;application/json; charset=UTF-8&quot;)

答案2

得分: 1

"bar: {test: %s}" 是一个你刚刚发明的随机、任意的编码方式,Rails 不可能理解如何解析它,除非你在 Rails 端也编写了一些自定义的解码器。

在通信渠道的一端发明新的数据编码方式是不可行的。你需要使用客户端和服务器都能理解的编码方式。对于 HTTP 来说,通常是将请求体编码为已知格式,例如 application/x-www-form-urlencoded

由于这是一个众所周知的标准,Go 提供了简单的方法来实现这一点;它会将数据编码到请求的主体中,并设置正确的 Content-Type 头,告诉 Rails 如何解码请求体:

data := url.Values{
    "bar[test]": "%s",
}

resp, err := http.PostForm("http://localhost:3000/bars.json", data)

希望对你有所帮助!

英文:

&quot;bar: {test: %s}&quot; is a random, arbitrary encoding that you've just invented, and Rails cannot possibly understand how to parse it, unless you've also written some custom decoder on the Rails side.

You can't invent new encodings of data on only one end of a communications channel. You need to stick to encodings that both the client and the server can understand. For HTTP, this typically means encoding your request body in a known format, for example application/x-www-form-urlencoded.

Because this is part of a well-known standard, Go provides ways for you to do this easily; it will handle encoding the data into the body of the request and setting the correct Content-Type header which tells Rails how to decode the body:

data := url.Values{
    &quot;bar[test]&quot;: &quot;%s&quot;       
}

resp, err := http.PostForm(&quot;http://localhost:3000/bars.json&quot;, data)

huangapple
  • 本文由 发表于 2022年7月8日 02:15:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/72902505.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定