首页 > 解决方案 > 如何使用 curl 发布而不收到 HTTP 错误 422 'Unprocessable Entity'?

问题描述

我正在尝试向登录端点发送 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 响应。

标签: ruby-on-railsformshttpcurl

解决方案


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

选项 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 或令牌或任何东西。


推荐阅读