英文:
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("bar: {test: %s}", data))
fmt.Println(string(body))
req, err := http.NewRequest(
"POST",
"http://localhost:3000/bars.json",
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'
app/controllers/bars_controller.rb:25:in `create'
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("{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)
And here is the Code for my 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
The Server side error:
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'
Is there an alternative way to format my request data so that the Rails API recognizes it as a hash?
答案1
得分: 1
- 这个
"bar: {test: %s}"
不是一个有效的 JSON 格式,请尝试使用"{ \"bar\": {\"test\": \"%s\"} }"
(注意引号和括号),最好使用json.Marshal
进行处理。 - 添加 JSON 内容类型头部
req.Header.Set("Content-Type", "application/json; charset=UTF-8")
。
英文:
- That's
"bar: {test: %s}"
not a valid json, try"{ "bar": {"test": "%s"} }"
(notice quotes and brackets), its better to usejson.Marshal
. - Add json content type header
req.Header.Set("Content-Type", "application/json; charset=UTF-8")
答案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)
希望对你有所帮助!
英文:
"bar: {test: %s}"
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{
"bar[test]": "%s"
}
resp, err := http.PostForm("http://localhost:3000/bars.json", data)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论