11class ReportsController < ApplicationController
2+ before_action :fix_missing_json_content_type
3+
4+ wrap_parameters false
5+
26 include ReportsHelper
37
48 protect_from_forgery :except => [ :create ]
59
6- DATA_KEY = %W! central_tendency error name ips stddev microseconds iterations cycles !
7-
810 def create
9- data = request . body . read
10-
11- begin
12- input = JSON . parse data
13- rescue Exception => err
14- logger . fatal ( "Error: #{ err . message } || #{ data } " )
15- head 400
16- return
17- end
18-
19- ary = input [ "entries" ]
20-
21- unless ary . kind_of? Array
22- head 400
23- return
24- end
25-
26- ary . each do |j |
27- needed = DATA_KEY . dup
28-
29- j . keys . each do |k |
30- if DATA_KEY . include? k
31- needed . delete k
32- else
33- head 400
34- return
35- end
36- end
11+ rep = Report . create! report_params
3712
38- unless needed . empty?
39- head 400
40- return
41- end
42- end
43-
44- rep = Report . create report : JSON . generate ( ary ) ,
45- ruby : input [ "ruby" ] ,
46- os : input [ "os" ] ,
47- arch : input [ "arch" ]
48-
49- options = input [ "options" ] || { }
13+ options = params [ "options" ] || { }
5014
5115 if options [ "compare" ]
5216 rep . compare = true
@@ -55,6 +19,8 @@ def create
5519 rep . save
5620
5721 render json : { id : rep . short_id }
22+ rescue ActionController ::ParameterMissing , ActiveRecord ::RecordInvalid
23+ head 400
5824 end
5925
6026 def show
@@ -64,7 +30,7 @@ def show
6430 fastest_val = nil
6531 note_high_stddev = false
6632
67- @report . data . each do |part |
33+ @report . entries . each do |part |
6834 if !fastest_val || part [ "ips" ] > fastest_val
6935 fastest = part
7036 fastest_val = part [ "ips" ]
@@ -78,4 +44,31 @@ def show
7844 @note_high_stddev = note_high_stddev
7945 @fastest = fastest
8046 end
47+
48+ private
49+ def report_params
50+ entries_params = params . require ( :entries ) . map do |entry |
51+ entry . permit ( :name , :ips , :central_tendency , :error , :stddev , :microseconds , :iterations , :cycles )
52+ end
53+ params . permit ( :ruby , :os , :arch ) . merge ( report : entries_params )
54+ end
55+
56+ # benchmark-ips sends the JSON string in the request body but it does not specify a content type
57+ # when that happens, Rails parses it incorrectly and produces a params key `"{\"entries\":"`
58+ #
59+ # we can detect this and fix the params object to properly parse the request body as JSON and update
60+ # the `params` object
61+ def fix_missing_json_content_type
62+ if params . keys . include? ( "{\" entries\" :" ) && request . body . present?
63+ begin
64+ json = JSON . parse ( request . body . read )
65+ params . delete ( "{\" entries\" :" )
66+ params . merge! ( json )
67+ rescue JSON ::ParserError
68+ # Body was not valid JSON, do nothing
69+ ensure
70+ request . body . rewind
71+ end
72+ end
73+ end
8174end
0 commit comments