Reputation: 405
My AMP form in Rails is returning this error in the terminal :
Completed 406 Not Acceptable in 338ms (ActiveRecord: 54.1ms)
ActionController::UnknownFormat (InscriptionsController#create is missing a template for this request format and variant.
request.formats: ["application/json"]
request.variant: []):
And in the browser :
POST http://localhost:3000/inscriptions?__amp_source_origin=http%3A%2F%2Flocalhost%3A3000 406 (Not Acceptable)
Response must contain the AMP-Access-Control-Allow-Source-Origin header
Form submission failed: Error: Response must contain the AMP-Access-Control-Allow-Source-Origin header
at bb.f.assert (https://cdn.ampproject.org/v0.js:21:319)
at y (https://cdn.ampproject.org/v0.js:26:213)
at https://cdn.ampproject.org/v0.js:179:339
However I did follow the CORS sample code provided by the official documentation https://amp.dev/documentation/guides-and-tutorials/learn/amp-caches-and-cors/amp-cors-requests?referrer=ampproject.org, and according to the AMP validation, everything is fine,
This is my controller :
def create
@inscription = Inscription.new(inscription_params)
@inscription.save
subscriber_email = inscription_params[:email].downcase
if Subscriber.where(email: subscriber_email).count == 0
@subscriber = Subscriber.new
@subscriber.email = subscriber_email
@subscriber.save
@new_subscriber = true
else
@subscriber = Subscriber.where(email: subscriber_email).first
@new_subscriber = false
end
[...]
respond_to do |format|
format.html { redirect_to root_path, notice: "Merci ! Nous avons bien reçu votre inscription !" }
format.js
format.json {
allowed_origins = ["https://example.com", "https://example.com.cdn.ampproject.org/", "http://example.com.amp.cloudflare.com", "https://cdn.ampproject.org"]
allowed_source_origin = "https://example.com"
source_origin = params[:__amp_source_origin]
origin = request.headers["Origin"]
response.set_header('Content-type', 'application/json')
response.set_header('Access-Control-Allow-Credentials', 'true')
response.set_header('Access-Control-Allow-Origin', origin)
response.set_header('AMP-Access-Control-Allow-Source-Origin', source_origin)
p response.headers
}
end
end
May you help me with this? I probably did something wrong with the headers.
Upvotes: 2
Views: 664
Reputation: 4378
I think the main issue here is not about unknown format, it's about template
In the error you showed, it is clear that you are sending the proper Content-Type in your request
request.formats: ["application/json"]
And you've specified format.json
in your controller action.
So the only thing that comes to mind is that there is an issue with the response of your request. Now again looking at the error message, it says you are missing a template.
ActionController::UnknownFormat (InscriptionsController#create is missing a template for this request format and variant
The reason for this is that you are not returning any json response from the controller action
format.json {
allowed_origins = ["https://example.com", "https://example.com.cdn.ampproject.org/", "http://example.com.amp.cloudflare.com", "https://cdn.ampproject.org"]
allowed_source_origin = "https://example.com"
source_origin = params[:__amp_source_origin]
origin = request.headers["Origin"]
response.set_header('Content-type', 'application/json')
response.set_header('Access-Control-Allow-Credentials', 'true')
response.set_header('Access-Control-Allow-Origin', origin)
response.set_header('AMP-Access-Control-Allow-Source-Origin', source_origin)
p response.headers
}
You need to either render json
directly from your controller action or if you don't do that then
Rails tries to find an appropriate template for your controller action.
and I think this is the main reason for this error.
1. Add a render statement to your controller action
In that case you can do something like this:
format.json {
allowed_origins = ["https://example.com", "https://example.com.cdn.ampproject.org/", "http://example.com.amp.cloudflare.com", "https://cdn.ampproject.org"]
allowed_source_origin = "https://example.com"
source_origin = params[:__amp_source_origin]
origin = request.headers["Origin"]
response.set_header('Content-type', 'application/json')
response.set_header('Access-Control-Allow-Credentials', 'true')
response.set_header('Access-Control-Allow-Origin', origin)
response.set_header('AMP-Access-Control-Allow-Source-Origin', source_origin)
p response.headers
render json: {}, status: :ok
}
2. Create appropriate view file so that Rails can find it
Rails will try to find a view file with as name as controller action in directory name of controller name. So in your case since the name of controller is InscriptionsController
so your file should be
app/views/inscriptions/create.json
In the link you provided, it is stated
For requests from the allowed origins, our response will contain the following headers:
Access-Control-Allow-Origin:
AMP-Access-Control-Allow-Source-Origin:
Access-Control-Expose-Headers: AMP-Access-Control-Allow-Source-Origin
But you are not setting the Access-Control-Expose-Headers
in your create action which should be set in order for client to read additional response headers in CORS request.
Upvotes: 4