【问题标题】:HTTParty: Post action is resulting in error Net::HTTPServerException (403 "Forbidden")HTTParty:后操作导致错误 Net::HTTPServerException (403 \"Forbidden\")
【发布时间】:2023-01-12 17:01:11
【问题描述】:

我正在尝试使用 httparty gem 实现 post 操作,这就是我所拥有的。我在 docker 中运行所有内容,下面的代码将作为活动作业运行。我在一项服务中,我正在尝试在其他服务中发布到 api。我能够得到但没有任何运气。我在网上看了很多,但我不确定我做错了什么。我总是在 self.class.post 行收到错误 403。我还尝试对 api 进行邮递员调用,我能够访问 api,但下面的代码甚至无法访问其他服务。

任何帮助表示赞赏。谢谢。

require 'uri'

class CustomerProductAPI
  include HTTParty
  format :json

  def initialize(customer_product_id)
    @customer_product = CustomerProduct.find(customer_product_id)
    @customer = Customer.find(@customer_product.student_id)
    @product = Product.find(@customer_product.product_id)
    self.class.base_uri environment_based_uri + '/customer_product_api'
  end

  def create_customer_product
    uri = URI(self.class.base_uri + "/customer/#{customer.id}")
    self.class.post(uri, body: body_hash).response.value
  end

  private

  attr_reader :customer_product, :customer, :product

  def body_hash
    {
      token: ENV['CUSTOMER_PRODUCT_API_TOKEN'],
      customer: customer.name,
      product: product.name,
    }
  end

  def environment_based_uri
    ENV['CUSTOMER_PRODUCT_URL']
  end
end

【问题讨论】:

  • 你的帖子成功了。 403 是来自服务器的消息,它拒绝传送您请求的内容,因为它认为您没有足够的权限。因此,您的 Ruby 似乎没有任何问题。根据 API 文档,检查您是否正确使用了 API,是否正在访问您有权访问的资源,是否提供了所需的任何授权令牌/密码等,以及令牌是否正确,并且当前的;如果还是不行,请向 API 的所有者寻求帮助。
  • 还要检查uri是否正确;我不确定,但我有一种直觉,你可能误用了self.class.base_uri(错误的 URI 可能解释了为什么 API 认为你正在访问你不应该访问的东西)
  • 确保 ENV['CUSTOMER_PRODUCT_URL'] 根据您的环境返回正确的值。

标签: ruby-on-rails ruby httparty


【解决方案1】:

虽然我们实际上无法确定接受响应的服务器究竟期望什么,但您肯定会在这里做很多非惯用的事情,这会加剧故障排除。

base_uri 应该只在类主体中设置。不在每个实例的initialize 中。

从 ENV 获取配置时,使用 ENV.fetch 而不是括号访问器,因为它会引发 KeyError 而不是让 nil 偷偷通过。

您不需要使用 HTTParty 构造 URI。只需传递一个路径,它就会构造相对于 base_uri 的请求 uri。

您的 HTTP 客户端类不应该关心查询数据库和处理在找不到记录时可能发生的潜在错误。这应该是调用客户端的控制器/作业/服务对象的责任。由于您实际上只使用了三个简单的属性,因此它实际上根本不需要记录作为输入,而且实际上更好的是它不必了解您的模型及其关联(或者在这种情况下不需要)。

class CustomerProductAPI
  # lets you stub/inspect the constant
  CUSTOMER_PRODUCT_URL = ENV.fetch('CUSTOMER_PRODUCT_URL') + '/customer_product_api'

  include HTTParty
  format :json
  base_uri CUSTOMER_PRODUCT_URL 

  def initialize(id:, product_name:, customer_name:)
    @id = id
    @product_name = product_name
    @customer_name = customer_name
  end

  def create_customer_product
    self.class.post("/customer/#{@id}", body: {
      token: ENV.fetch('CUSTOMER_PRODUCT_API_TOKEN'),
      customer: @customer_name,
      product: @product_name
    })
    # don't return .response.value as it will make error handling impossible. 
    # either handle unsuccessful responses here or return the whole response 
    # for the consumer to handle it.
  end
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-21
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    • 2020-06-07
    • 1970-01-01
    相关资源
    最近更新 更多