如何使用curl进行发布而不获取HTTP错误422“无法处理的实体”?

时间:2019-02-08 12:13:45

标签: ruby-on-rails forms http curl

我正在尝试向登录端点发送POST请求。我不断收到HTTP错误422 'Unprocessable Entity'。如何克服这个错误?

以下是我尝试过的一些命令示例:

curl -v -X POST -F 'user[email]=test@email.com' -F 'user[password]=password' https://example.com/users/sign_in

curl -v -H 'Accept: text/html,application/xhtml+xml,application/xml;' -H 'Content-Type: application/x-www-form-urlencoded' -d 'utf8=%E2%9C%93&authenticity_token=123456789123456789123456789123123123456456456789789789789VX4KgMBr6zgGjo123456789123456789njQ%3D%3D&user%5Bemail%5D=test%40sign_in.com&user%5Bpassword%5D=password&commit=Sign+in' https://example.com/users/sign_in

我希望请求发送回200301 / 302响应状态,但是我得到了:

* upload completely sent off: 208 out of 208 bytes
< HTTP/1.1 422 Unprocessable Entity
< Server: nginx/1.12.2
< Date: Fri, 08 Feb 2019 12:08:07 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 0
< Connection: keep-alive
< X-Request-Id: 6ceb5baa-7740-448a-8105-6f67dd203fbb
< X-Runtime: 0.021676

任何帮助或建议,我们将不胜感激。谢谢

更新

我现在看到来自此类请求的Rails日志呈现了InvalidAuthenticityToken错误

Started POST "/users/sign_in" for 127.0.0.1 at 2019-02-08 14:30:50 +0000
Processing by Users::SessionsController#create as */*
Can't verify CSRF token authenticity.
Completed 422 Unprocessable Entity in 1ms (ActiveRecord: 0.0ms)

ActionController::InvalidAuthenticityToken - ActionController::InvalidAuthenticityToken:

关于如何克服这一点的任何想法?我要做的就是确保需要身份验证的路由返回200/301/302响应。

1 个答案:

答案 0 :(得分:0)

至少有两种方法可以做到这一点:

选项 1:获取和使用令牌

解决此问题的一种方法是实际捕获并利用 rails 生成的真实性令牌。为此,我们还需要捕获并发送回 cookie,以允许我们利用与生成的令牌相关联的会话。我能够让它与以下咒语一起使用。

(注意:我假设已经为“事物”创建了一个脚手架,创建了一个 things_controller.rb 等。根据需要将其调整到您的用例中。)

步骤 1:捕获令牌:

token=$(curl -s -c myjar https://example.com/things/new | \
     sed -n 's/.*name="authenticity_token" value="\([^"]*\)".*/\1/p')

第 2 步:在请求中使用它:

cat myjar | \
  curl -b - -s \
        -H "Accept: application/json" \
        -H "Content-type: application/json" \
        -d '{"thing": {"field1":"Test","field2":"Testing"},
             "authenticity_token":"'"$token"'"}' \
        https://example.com/things | jq .

这有效,无需对应用程序进行任何更改。当我运行它时,我看到了一个漂亮的 JSON 渲染,从一个成功的对象创建作为输出。

(如果您只想要原始 JSON 数据,请忽略 | jq .,也许会将其发送到其他地方。)

然而,还有另一种选择。对控制器稍作调整,就可以更轻松地使用 curl(不需要 cookiejar,参数更少,只有一个 curl 命令,并且没有奇怪的嵌套引号),如下所示:


选项 2:禁用令牌检查:

解决此问题的另一种方法是在您希望允许此类操作的任何控制器中禁用对 validity_token 操作的 create 检查。例如,以我的名为“thing”的脚手架为例,您可能会更新 app/controllers/things_controller.rb 文件以添加此处显示的第二行:

class ThingsController < ApplicationController                     # EXISTING LINE
  skip_before_action :verify_authenticity_token, only: [:create]   # NEW LINE
  before_action :set_img, only: [:show, :edit, :update, :destroy]  # EXISTING LINE
  # ... additional content elided ...

然后 rails 根本不会做那个检查,所以你可以做一个像这样的一步请求:

curl -s \
  -H "Accept: application/json" \
  -H "Content-type: application/json" \
  -d '{"thing": {"field1":"Test","field2":"Testing"}}' \
  http://example.com/things | jq .

我再次看到 jq 生成的输出,这次无需捕获 cookie 或令牌或任何东西。