2013-06-11 27 views
21

Tôi đang viết một API và nó nhận được một tải trọng JSON làm cơ quan yêu cầu.Làm cách nào để phân tích cú pháp nội dung yêu cầu JSON trong Sinatra chỉ một lần và hiển thị nó cho tất cả các tuyến đường?

Để có được vào nó hiện nay, tôi đang làm một cái gì đó như thế này:

post '/doSomething' do 
    request.body.rewind 
    request_payload = JSON.parse request.body.read 

    #do something with request_payload 
    body request_payload['someKey'] 
end 

một cách tốt để trừu tượng này đi vì vậy mà tôi không cần phải làm điều đó cho mỗi tuyến đường là gì? Một số tuyến đường của tôi phức tạp hơn điều này, và kết quả là request.body sẽ nhận được đọc lại và lặp lại nhiều lần trên mỗi tuyến đường với cách tiếp cận này, mà tôi muốn tránh.

Có cách nào để làm cho request_payload chỉ khả dụng một cách kỳ diệu cho các tuyến đường không? Như thế này:

post '/doSomething' do 
    #do something with request_payload, it's already parsed and available 
    body request_payload['someKey'] 
end 

Trả lời

46

Sử dụng một Sinatra trước khi xử lý:

before do 
    request.body.rewind 
    @request_payload = JSON.parse request.body.read 
end 

này sẽ phơi bày nó để xử lý yêu cầu hiện tại. Nếu bạn muốn nó tiếp xúc với tất cả các trình xử lý, hãy đặt nó trong một lớp cha và mở rộng lớp đó trong các trình xử lý của bạn.

+0

Đó là bản năng đầu tiên của tôi, nhưng điều này có hoạt động với async-sinatra không? Tôi sợ các yêu cầu tiếp theo có thể ghi đè lên các yêu cầu đó trong khi các yêu cầu trước đó vẫn đang trong quá trình bay? – lms

+1

Sinatra * nên * tạo một phiên bản mới của mỗi trình xử lý cho mỗi yêu cầu, do đó, miễn là bạn sử dụng một biến mức cá thể, nó sẽ là ok. Chúng tôi sử dụng một chương trình tương tự và không thấy bằng chứng về điều kiện chủng tộc đang được tải. – mcfinnigan

+0

Bộ lọc 'trước' [có thể] (http://www.sinatrarb.com/intro.html#Filters) được xác định dựa trên mẫu tuyến đường nhưng dường như không phải là phương thức HTTP. Bummer - làm điều này cho chỉ POST là một trường hợp sử dụng hợp lý. – mgold

1

Như thế này làm việc cho Sinatra 1.4.5

before do 
    if request.body.size > 0 
    request.body.rewind 
    @params = ActiveSupport::JSON.decode(request.body.read) 
    end 
end 
7

Bạn cũng có thể sử dụng rack Middleware để phân tích nó. Xem https://github.com/rack/rack-contrib Chỉ cần use Rack::PostBodyContentTypeParser khi khởi tạo lớp Sinatra của bạn.

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