2012-04-18 33 views
17

Tôi có một phương thức điều khiển trong Ruby on Rails 3 chấp nhận ứng dụng/JSON làm loại nội dung. Điều này tất cả hoạt động như mong đợi, nhưng tôi thực sự không muốn các đường ray tự động phân tích cú pháp JSON trong phần thân của yêu cầu POST. Phương thức này hoạt động như một cổng và chỉ chuyển thông tin vào hàng đợi và có thể khá lớn. Tôi không muốn lãng phí thời gian xử lý dữ liệu vào @_params vì nó không cần thiết.Ngăn chặn ruby ​​trên đường ray 3 từ phân tích cú pháp bài đăng JSON

Tôi tin rằng tôi có thể giải quyết vấn đề này bằng cách đặt loại nội dung trong tiêu đề của yêu cầu cho một thứ khác, nhưng tôi muốn chính xác về mặt ngữ nghĩa cho các yêu cầu HTTP.

Làm cách nào để tắt chức năng này?

CHỈNH SỬA: cụ thể hơn cách tôi có thể chỉnh sửa chức năng này cho chỉ một tuyến đường này?

+0

Bạn biết đấy, nếu bạn Đăng nó như JSON và nói với đường ray để mong đợi nó được đăng dưới dạng JSON, tôi nghĩ Rails sẽ luôn phân tích cú pháp. Để làm những gì bạn mô tả tôi nghĩ bạn gần như muốn gắn một điểm cuối rack trên tuyến đường đó và xử lý POST với một tiện ích như 'rack_raw_upload' ... Câu hỏi hay, xin lỗi tôi không thực sự biết câu trả lời. – Andrew

+0

Thú vị nghĩ ... Tôi có thể cho rằng một shot và xem nó như thế nào. – Macdiesel

Trả lời

13

Phân tích tham số được nướng khá sâu bên trong actionpack lib/action_dispatch/middleware/params_parser.rb.

Tôi muốn nói rằng điều tốt nhất bạn sẽ tránh được là ngăn chặn yêu cầu với Rack, một cái gì đó như thế này.

Trong lib/raw_json.rb

module Rack 
    class RawJSON 
    def initialize(app) 
     @app = app 
    end 

    def call(env) 
     request = Request.new(env) 
     if request.content_type =~ /application\/json/i 
     # test request.path here to limit your processing to particular actions 
     raw_json = env['rack.input'].read 
     env['CONTENT_TYPE'] = 'application/x-www-form-urlencoded' 
     env['rack.input'] = StringIO.new("raw_json=#{raw_json}") 
     end 
     return @app.call(env) 
    end 
    end 
end 

Trong config.ru, chèn này trước khi cuộc gọi đến run <your app name>::Application

require 'raw_json' 
use Rack::RawJSON 
+0

có vẻ như tất cả những gì bạn cần thêm vào giải pháp này là phát hiện một tuyến đường nhất định - ví dụ: 'if request.path == '/ foo' và request.content_type = ~/application \/json/i' –

+0

Vâng, đó là lý do tại sao tôi đặt một chú thích trong đoạn mã để kiểm tra request.path. –

+0

Tôi chưa thử điều này, nhưng có vẻ như là một giải pháp hợp lý, tôi sẽ chụp. – Macdiesel

1

Các nguyên cần thiết cho phân tích cú pháp JSON từ một yêu cầu duy nhất là tương đối thấp. Bạn có lý do cụ thể nào để tin rằng việc xử lý JSON đang góp phần vào bất kỳ sự chậm chạp nào trong quá trình xử lý tổng thể không?

Nếu không, thì tôi khuyên bạn nên để nguyên trạng này cho đến khi có thể xác định được thời gian đó là sự cố.

Định cấu hình đường ray để không phân tích cú pháp JSON (thông qua một số loại cấu hình giá hoặc phương pháp khác) sẽ tạo ít nhất một tuyến trong ứng dụng của bạn không được xử lý theo tiêu chuẩn Đường ray.

Cuối cùng, bạn có thể thấy mình phải thực hiện một số loại xử lý dữ liệu này. Hoặc có lẽ bạn sẽ cần phải đặt một số loại bảo mật ở phía trước của nó. Hoặc có thể bạn sẽ muốn đăng nhập và liên kết nó với người dùng đã gửi nó. Và khi ngày đó đến với bạn (hoặc người khác trong nhóm của bạn) sẽ cần phải đi vào và thực hiện các thay đổi đối với việc triển khai không chuẩn này.

Thực hiện mọi việc theo cách không chuẩn trong triển khai Rails có thể thêm vào độ phức tạp và thời gian để duy trì phần mềm. Nó cũng là một nguồn phổ biến của các khuyết tật vì mọi người ít quen thuộc với việc xử lý không chuẩn. Vì vậy, trừ khi nó là một vấn đề thực sự, tôi khuyên bạn nên chỉ cho phép rails xử lý JSON và sau đó chỉ cần vượt qua nó thông qua Rails Way bình thường.

+1

Điều này không trả lời được câu hỏi. Tôi đang tìm cách để không phân tích các phản ứng json đến chủ yếu là vì lợi ích của tối ưu hóa. Cơ thể json có khả năng có thể là một mảng với hàng chục nghìn mục và phải phân tích cú pháp và lặp lại điều này sẽ mất cả thời gian và bộ nhớ từ ứng dụng khi nó có thể/nên làm những việc khác. Hành động này chỉ đơn thuần là đi qua cho dữ liệu. – Macdiesel

+0

Nó không phải là tương đối thấp ở tất cả, Rails phân tích toàn bộ đầu vào, bộ lọc và các bản ghi TẤT CẢ các thông số và chi phí là HUGE khi giao dịch với nhiều yêu cầu có kích thước 100k. – lzap

1

Nó có thể được nướng trong, nhưng nhìn vào mã:

module ActionDispatch 
    class ParamsParser 
    DEFAULT_PARSERS = { 
     Mime::XML => :xml_simple, 
     Mime::JSON => :json 
    } 

    def initialize(app, parsers = {}) 
     @app, @parsers = app, DEFAULT_PARSERS.merge(parsers) 
    end 

    [ ... ] 

     strategy = @parsers[mime_type] 

Vì vậy, nếu bạn có thể sắp xếp để gửi một băm để khởi tạo này, bạn có thể thêm hoặc ghi đè mặc định. Không chắc chắn cho phép loại bỏ, nhưng một phương pháp phân tích cú pháp trống có thể làm việc.

parsers trả lời ở đây: How do I initialize ActionDispatch::ParamsParser in Rails 3.1?

Mã là từ actionpack-3.2.8/lib/action_dispatch/middleware/params_parser.rb

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