访问被拒绝,你可能没有权限或未登录。

Rails response content-type negotiation 的一些问题

hmsk86 · 2025年11月11日 · 最后由 amonlei-github 回复于 2025年11月14日 · 158 次阅读

学习 controller 的 respond_to 方法时遇到的一个问题

# app/controllers/test_controller.rb
class TestController < ApplicationController
  def create
    params = self.params.expect user: [ :name, :email ]
    name = params[:name]
    email = params[:email]
    respond_to do |format|
      format.html { render html: "这是html: name=#{name} email=#{email}" }
      format.json { render json: { msg: "这是json", **params } }
    end
  end
end

# config/route.rb
Rails.application.routes.draw do
  post "/test", to: "test#create"
end

用 httpie 发送 post 请求,注意请求头带有Accept: application/json, */*;q=0.5,按理说应该返回 json 响应,但是 rails 返回了 html 响应

$ http POST http://localhost:3000/test user[name]=foo user[email][email protected] --verbose
POST /test HTTP/1.1
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 53
User-Agent: HTTPie/3.2.4
Accept: application/json, */*;q=0.5
Content-Type: application/json
Host: localhost:3000

{"user": {"name": "foo", "email": "[email protected]"}}

HTTP/1.1 200 OK
x-frame-options: SAMEORIGIN
x-xss-protection: 0
x-content-type-options: nosniff
x-permitted-cross-domain-policies: none
referrer-policy: strict-origin-when-cross-origin
content-type: text/html; charset=utf-8
etag: W/"644544dc838ec7f5f9d146a6efaf52af"
cache-control: max-age=0, private, must-revalidate
x-request-id: ef6be23e-f655-4368-ad0e-5561c1b975ac
x-runtime: 0.002610
server-timing: start_processing.action_controller;dur=0.01, render_template.action_view;dur=0.01, process_action.action_controller;dur=1.32
content-length: 42

这是html: name=foo [email protected]

Accept: application/json, */*;q=0.5改成Accept: application/json就行了,也就是说,如果请求头的Accept带有*/*,那么 rails 一律返回 html 响应,无视优先级

$ http POST http://localhost:3000/test user[name]=foo user[email][email protected] Accept:'application/json' --verbose
POST /test HTTP/1.1
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 53
User-Agent: HTTPie/3.2.4
Accept: application/json
Content-Type: application/json
Host: localhost:3000

{"user": {"name": "foo", "email": "[email protected]"}}

HTTP/1.1 200 OK
x-frame-options: SAMEORIGIN
x-xss-protection: 0
x-content-type-options: nosniff
x-permitted-cross-domain-policies: none
referrer-policy: strict-origin-when-cross-origin
content-type: application/json; charset=utf-8
vary: Accept
etag: W/"f1ca37f45944a0eb8cc6bc093b6fc5c8"
cache-control: max-age=0, private, must-revalidate
x-request-id: cdf64112-4d57-4569-af76-ce712b165fe9
x-runtime: 0.001742
server-timing: start_processing.action_controller;dur=0.01, process_action.action_controller;dur=0.31
content-length: 59

{"msg":"这是json","name":"foo","email":"[email protected]"}
需要 登录 后方可回复, 如果你还没有账号请 注册新账号