2012-03-10 23 views
13

Bắt đầu với Rails 3.0, theo thời gian, tôi đã nhận được thông báo ngoại lệ như thế này:đàn áp ActionView :: ngoại lệ MissingTemplate cho Rails 3.x

ActionView::MissingTemplate: Missing template [...] with {:locale=>[:en], 
    :formats=>[:text], :handlers=>[:erb, :builder, :haml]}. Searched in: * [...] 

Ví dụ, một tùy ý viết tay URL như http://example.com/some/path/robots.txt làm tăng lỗi. Không vui.

Tôi đã báo cáo sự cố trong vé này cách đây khá lâu và đã sử dụng bản vá được đề cập ở đây, nhưng sự cố vẫn tiếp diễn.

https://rails.lighthouseapp.com/projects/8994/tickets/6022-content-negotiation-fails-for-some-headers-regression

Một sửa chữa được đề xuất trong bài viết trên blog này,

http://trevorturk.wordpress.com/2011/12/09/handling-actionviewmissingtemplate-exceptions/

Để sử dụng này:

Nhưng nó không cảm thấy đúng với tôi, như tôi 'm không quan tâm đến quá tải một hành động với nhiều định dạng. Trong ứng dụng của tôi, có các URL riêng biệt cho HTML và JSON API, do đó, đơn giản render là đủ.

Tôi có nên nuốt ngoại lệ theo số rescue_from ActionView::MissingTemplate và trả lại 406 bản thân mình không?

Có cách nào tốt hơn để xử lý tình huống này không?

Hoặc tôi có thể hỏi theo cách này - ngay từ đầu, có bất kỳ sự hữu ích trong thế giới thực nào trong việc tăng loại ngoại lệ này lên sản xuất không?

Trả lời

5

Nếu bạn không cần các tuyến đường được định dạng, bạn có thể tắt chúng với: format => false trong đặc tả tuyến đường của bạn, ví dụ:

get '/products' => 'products#index', :format => false 

Điều này sẽ tạo ra RoutingError được chuyển thành 404 Không tìm thấy. Hoặc bạn có thể hạn chế nó đến một số định dạng được xác định trước:

get '/products' => 'products#index', :format => /(?:|html|json)/ 

Nếu bạn muốn có một url định dạng nhưng muốn nó giới hạn trong một định dạng duy nhất sau đó bạn có thể làm điều này:

get '/products.json' => 'products#index', :format => false, :defaults => { :format => 'json' } 

Có một số các lý do hợp lệ để nâng cao lỗi này trong sản xuất - một tệp bị thiếu từ một triển khai ví dụ hoặc có thể bạn muốn thông báo về một người nào đó đang cố gắng tấn công các url của ứng dụng của bạn.

+6

Cảm ơn bạn. Kết luận của tôi vào thời điểm này là hầu hết vấn đề là với ': format'. Có cách nào để vô hiệu hóa ': format' hoàn toàn không? Tôi không muốn thêm ': format => false' vào mọi định nghĩa. – kenn

0

Nếu có các đường dẫn cụ thể được gọi là tạo lỗi - và chúng là cùng một bộ url được gọi thường xuyên (ví dụ: robots.txt hoặc bất kỳ thứ gì) - điều tốt nhất cần làm nếu bạn có thể để loại bỏ chúng khỏi đánh máy chủ đường ray của bạn để bắt đầu.

Cách thực hiện việc này tùy thuộc vào chồng máy chủ của bạn. Một cách để thực hiện việc này là chặn trực tiếp số này theo số RACK trước khi url được chuyển vào đường ray.

Cách khác có thể chặn nó trong NGINX hoặc Unicorn, tùy thuộc vào trình nghe web bạn đang sử dụng cho ứng dụng của mình.

Tôi khuyên bạn nên xem xét điều này và sau đó quay lại và đăng câu hỏi bổ sung ở đây về 'Cách chặn URL bằng Rack?"(Hoặc unicorn hoặc nginx hoặc bất cứ nơi nào bạn nghĩ rằng nó có ý nghĩa để chặn truy cập.

+0

Tôi không nghĩ đó là một cách bền vững để xử lý loại vấn đề này, vì bản chất của vấn đề này không lặp đi lặp lại mà là ngẫu nhiên. Bạn sẽ thấy theo thời gian RẤT URL lạ bị đánh. Tôi có một số thiết lập Nginx để xếp hạng giới hạn hoặc loại bỏ các yêu cầu không mong muốn, nhưng vé này không phải là nó. – kenn

1

Nếu bạn có tài nguyên sẽ chỉ được phân phối ở một định dạng và bạn muốn bỏ qua bất kỳ tiêu đề Chấp nhận nào định dạng mặc định, bạn có thể loại bỏ định dạng từ mẫu filename vì vậy, ví dụ, nếu bạn có:.

app/views/some/path/robots.txt.erb 

bạn có thể thay đổi nó chỉ đơn giản là

app/views/some/path/robots.erb 

một số trường phái tư tưởng có thể nói đây là một điều xấu vì bạn đang trả về dữ liệu trong một forma khác Từ những gì được yêu cầu, tuy nhiên trong thực tế có rất nhiều tác nhân người dùng không đúng, không phải mọi trang web đều lọc các yêu cầu loại nội dung một cách cẩn thận và trả về cùng một điều là hành vi có thể dự đoán được, vì vậy tôi nghĩ đây là một cách hợp lý.

2

Sau khi một số nguồn lặn tôi tìm thấy một cách khác. Đặt điều này trong một initializer.

ActionDispatch::ExceptionWrapper.rescue_responses.merge! 'ActionView::MissingTemplate' => :not_found 
1

Hãy thử thêm

render nothing: true 

ở phần cuối của phương pháp của bạn.

3

rằng tốt nhất làm việc cho tôi là trong application_controller.rb:

rescue_from ActionView::MissingTemplate, with: :not_found 
+0

Điều này rất nguy hiểm vì bạn sẽ không thấy lỗi khi sản xuất nếu bạn gõ tên mẫu. –

Các vấn đề liên quan