学习 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]"}