From 0945dadc53892062df59f624ecce7b0429696cca Mon Sep 17 00:00:00 2001 From: Michał Młoźniak Date: Wed, 21 Jan 2015 20:23:21 +0100 Subject: [PATCH] Rename JsonParser to AirbrakeApi::V3::NoticeParser --- app/controllers/api/v3/notices_controller.rb | 4 ++-- lib/airbrake_api/params_error.rb | 3 +++ lib/airbrake_api/v3/notice_parser.rb | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/json_parser.rb | 85 ------------------------------------------------------------------------------------- spec/lib/airbrake_api/v3/notice_parser_spec.rb | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ spec/lib/json_parser_spec.rb | 69 --------------------------------------------------------------------- 6 files changed, 175 insertions(+), 156 deletions(-) create mode 100644 lib/airbrake_api/params_error.rb create mode 100644 lib/airbrake_api/v3/notice_parser.rb delete mode 100644 lib/json_parser.rb create mode 100644 spec/lib/airbrake_api/v3/notice_parser_spec.rb delete mode 100644 spec/lib/json_parser_spec.rb diff --git a/app/controllers/api/v3/notices_controller.rb b/app/controllers/api/v3/notices_controller.rb index a893f65..96437d8 100644 --- a/app/controllers/api/v3/notices_controller.rb +++ b/app/controllers/api/v3/notices_controller.rb @@ -9,7 +9,7 @@ class Api::V3::NoticesController < ApplicationController response.headers['Access-Control-Allow-Headers'] = 'origin, content-type, accept' if !request.options? - report = JsonParser.new(params).report + report = AirbrakeApi::V3::NoticeParser.new(params).report if report.valid? if report.should_keep? @@ -28,7 +28,7 @@ class Api::V3::NoticesController < ApplicationController else render nothing: true end - rescue JsonParser::ParamsError + rescue AirbrakeApi::ParamsError render text: 'Invalid request' end end diff --git a/lib/airbrake_api/params_error.rb b/lib/airbrake_api/params_error.rb new file mode 100644 index 0000000..2e1bb7a --- /dev/null +++ b/lib/airbrake_api/params_error.rb @@ -0,0 +1,3 @@ +module AirbrakeApi + class ParamsError < StandardError; end +end \ No newline at end of file diff --git a/lib/airbrake_api/v3/notice_parser.rb b/lib/airbrake_api/v3/notice_parser.rb new file mode 100644 index 0000000..96c80d4 --- /dev/null +++ b/lib/airbrake_api/v3/notice_parser.rb @@ -0,0 +1,89 @@ +module AirbrakeApi + module V3 + class NoticeParser + class ParamsError < StandardError; end + + attr_reader :params, :error + + def initialize(params) + @params = params || {} + end + + def report + attributes = { + error_class: error['type'], + message: error['message'], + backtrace: backtrace, + request: request, + server_environment: server_environment, + api_key: params['key'].present? ? params['key'] : params['project_id'], + notifier: params['notifier'], + user_attributes: user_attributes + } + + ErrorReport.new(attributes) + end + + private + + def error + raise ParamsError unless params.has_key?('errors') && params['errors'].any? + @error ||= params['errors'].first + end + + def backtrace + error['backtrace'].map do |backtrace_line| + { + method: backtrace_line['function'], + file: backtrace_line['file'], + number: backtrace_line['line'], + column: backtrace_line['column'] + } + end + end + + def server_environment + { + 'environment-name' => context['environment'], + 'hostname' => hostname, + 'project-root' => context['rootDirectory'], + 'app-version' => context['version'] + } + end + + def request + environment = params['environment'].merge( + 'HTTP_USER_AGENT' => context['userAgent'] + ) + + { + 'cgi-data' => environment, + 'session' => params['session'], + 'params' => params['params'], + 'url' => url, + 'component' => context['component'], + 'action' => context['action'] + } + end + + def user_attributes + hash = context.slice('userId', 'userUsername', 'userName', 'userEmail') + Hash[hash.map { |key, value| [key.sub(/^user/, ''), value] }] + end + + def url + context['url'] + end + + def hostname + URI.parse(url).hostname + rescue URI::InvalidURIError + '' + end + + def context + @context = params['context'] || {} + end + end + end +end \ No newline at end of file diff --git a/lib/json_parser.rb b/lib/json_parser.rb deleted file mode 100644 index 7f6fab1..0000000 --- a/lib/json_parser.rb +++ /dev/null @@ -1,85 +0,0 @@ -class JsonParser - class ParamsError < StandardError; end - - attr_reader :params, :error - - def initialize(params) - @params = params || {} - end - - def report - attributes = { - error_class: error['type'], - message: error['message'], - backtrace: backtrace, - request: request, - server_environment: server_environment, - api_key: params['project_id'] || params['key'], - notifier: params['notifier'], - user_attributes: user_attributes - } - - ErrorReport.new(attributes) - end - - private - - def error - raise ParamsError unless params.has_key?('errors') && params['errors'].any? - @error ||= params['errors'].first - end - - def backtrace - error['backtrace'].map do |backtrace_line| - { - method: backtrace_line['function'], - file: backtrace_line['file'], - number: backtrace_line['line'], - column: backtrace_line['column'] - } - end - end - - def server_environment - { - 'environment-name' => context['environment'], - 'hostname' => hostname, - 'project-root' => context['rootDirectory'], - 'app-version' => context['version'] - } - end - - def request - environment = params['environment'].merge( - 'HTTP_USER_AGENT' => context['userAgent'] - ) - - { - 'cgi-data' => environment, - 'session' => params['session'], - 'params' => params['params'], - 'url' => url, - 'component' => context['component'], - 'action' => context['action'] - } - end - - def user_attributes - hash = context.slice('userId', 'userUsername', 'userName', 'userEmail') - Hash[hash.map { |key, value| [key.sub(/^user/, ''), value] }] - end - - def url - context['url'] - end - - def hostname - URI.parse(url).hostname - rescue URI::InvalidURIError - '' - end - - def context - @context = params['context'] || {} - end -end \ No newline at end of file diff --git a/spec/lib/airbrake_api/v3/notice_parser_spec.rb b/spec/lib/airbrake_api/v3/notice_parser_spec.rb new file mode 100644 index 0000000..d414cf7 --- /dev/null +++ b/spec/lib/airbrake_api/v3/notice_parser_spec.rb @@ -0,0 +1,81 @@ +describe AirbrakeApi::V3::NoticeParser do + let(:app) { Fabricate(:app) } + + it 'raises error when errors attribute is missing' do + expect { + AirbrakeApi::V3::NoticeParser.new({}).report + }.to raise_error(AirbrakeApi::V3::NoticeParser::ParamsError) + + expect { + AirbrakeApi::V3::NoticeParser.new({'errors' => []}).report + }.to raise_error(AirbrakeApi::V3::NoticeParser::ParamsError) + end + + it 'parses JSON payload and returns ErrorReport' do + params = build_params(api_key: app.api_key) + + report = AirbrakeApi::V3::NoticeParser.new(params).report + notice = report.generate_notice! + + expect(report.error_class).to eq('Error') + expect(report.message).to eq('Error: TestError') + expect(report.backtrace.lines.size).to eq(9) + expect(notice.user_attributes).to include({'Id' => 1, 'Name' => 'John Doe', 'Email' => 'john.doe@example.org', 'Username' => 'john'}) + expect(notice.session).to include('isAdmin' => true) + expect(notice.params).to include('returnTo' => 'dashboard') + expect(notice.env_vars).to include( + 'navigator_vendor' => 'Google Inc.', + 'HTTP_USER_AGENT' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36' + ) + end + + it 'parses JSON payload when api_key is missing but project_id is present' do + params = build_params(api_key: nil, project_id: app.api_key) + + report = AirbrakeApi::V3::NoticeParser.new(params).report + expect(report).to be_valid + end + + def build_params(options = {}) + JSON.parse(<<-EOL) + { + "notifier":{"name":"airbrake-js-v8","version":"0.3.10","url":"https://github.com/airbrake/airbrake-js"}, + "errors":[ + { + "type":"Error", + "message":"Error: TestError", + "backtrace":[ + {"function":"d","file":"http://localhost:3000/assets/application.js","line":11234,"column":24}, + {"function":"c","file":"http://localhost:3000/assets/application.js","line":11233,"column":18}, + {"function":"b","file":"http://localhost:3000/assets/application.js","line":11232,"column":18}, + {"function":"a","file":"http://localhost:3000/assets/application.js","line":11231,"column":18}, + {"function":"HTMLDocument.","file":"http://localhost:3000/assets/application.js","line":11236,"column":3}, + {"function":"fire","file":"http://localhost:3000/assets/application.js","line":1018,"column":34}, + {"function":"Object.self.fireWith [as resolveWith]","file":"http://localhost:3000/assets/application.js","line":1128,"column":13}, + {"function":"Function.jQuery.extend.ready","file":"http://localhost:3000/assets/application.js","line":417,"column":15}, + {"function":"HTMLDocument.DOMContentLoaded","file":"http://localhost:3000/assets/application.js","line":93,"column":14} + ] + } + ], + "context":{ + "language":"JavaScript", + "sourceMapEnabled":true, + "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36", + "url":"http://localhost:3000/kontakt", + "userId":1,"userUsername":"john", + "userName":"John Doe", + "userUsername": "john", + "userEmail":"john.doe@example.org", + "version":"1.0", + "component":"ContactsController", + "action":"show" + }, + "params":{"returnTo":"dashboard"}, + "environment":{"navigator_vendor":"Google Inc."}, + "session":{"isAdmin":true}, + "key":"#{options[:api_key]}", + "project_id":"#{options[:project_id]}" + } + EOL + end +end \ No newline at end of file diff --git a/spec/lib/json_parser_spec.rb b/spec/lib/json_parser_spec.rb deleted file mode 100644 index cd85aec..0000000 --- a/spec/lib/json_parser_spec.rb +++ /dev/null @@ -1,69 +0,0 @@ -describe JsonParser do - let(:app) { Fabricate(:app) } - - it 'raises error when errors attribute is missing' do - expect { - JsonParser.new({}).report - }.to raise_error(JsonParser::ParamsError) - - expect { - JsonParser.new({'errors' => []}).report - }.to raise_error(JsonParser::ParamsError) - end - - it 'parses JSON payload and returns ErrorReport' do - params = JSON.parse(<<-EOL) - { - "notifier":{"name":"airbrake-js-v8","version":"0.3.10","url":"https://github.com/airbrake/airbrake-js"}, - "errors":[ - { - "type":"Error", - "message":"Error: TestError", - "backtrace":[ - {"function":"d","file":"http://localhost:3000/assets/application.js","line":11234,"column":24}, - {"function":"c","file":"http://localhost:3000/assets/application.js","line":11233,"column":18}, - {"function":"b","file":"http://localhost:3000/assets/application.js","line":11232,"column":18}, - {"function":"a","file":"http://localhost:3000/assets/application.js","line":11231,"column":18}, - {"function":"HTMLDocument.","file":"http://localhost:3000/assets/application.js","line":11236,"column":3}, - {"function":"fire","file":"http://localhost:3000/assets/application.js","line":1018,"column":34}, - {"function":"Object.self.fireWith [as resolveWith]","file":"http://localhost:3000/assets/application.js","line":1128,"column":13}, - {"function":"Function.jQuery.extend.ready","file":"http://localhost:3000/assets/application.js","line":417,"column":15}, - {"function":"HTMLDocument.DOMContentLoaded","file":"http://localhost:3000/assets/application.js","line":93,"column":14} - ] - } - ], - "context":{ - "language":"JavaScript", - "sourceMapEnabled":true, - "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36", - "url":"http://localhost:3000/kontakt", - "userId":1,"userUsername":"john", - "userName":"John Doe", - "userUsername": "john", - "userEmail":"john.doe@example.org", - "version":"1.0", - "component":"ContactsController", - "action":"show" - }, - "params":{"returnTo":"dashboard"}, - "environment":{"navigator_vendor":"Google Inc."}, - "session":{"isAdmin":true}, - "key":"#{app.api_key}" - } - EOL - - report = JsonParser.new(params).report - notice = report.generate_notice! - - expect(report.error_class).to eq('Error') - expect(report.message).to eq('Error: TestError') - expect(report.backtrace.lines.size).to eq(9) - expect(notice.user_attributes).to include({'Id' => 1, 'Name' => 'John Doe', 'Email' => 'john.doe@example.org', 'Username' => 'john'}) - expect(notice.session).to include('isAdmin' => true) - expect(notice.params).to include('returnTo' => 'dashboard') - expect(notice.env_vars).to include( - 'navigator_vendor' => 'Google Inc.', - 'HTTP_USER_AGENT' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36' - ) - end -end \ No newline at end of file -- libgit2 0.21.2