Skip to content

Commit

Permalink
feat: improve error message when request has non UTF-8 characters (#559)
Browse files Browse the repository at this point in the history
  • Loading branch information
bethesque authored May 21, 2022
1 parent 6035579 commit 3addc0c
Show file tree
Hide file tree
Showing 23 changed files with 143 additions and 105 deletions.
5 changes: 1 addition & 4 deletions lib/pact_broker/api/resources/all_webhooks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,7 @@ def post_is_create?
end

def malformed_request?
if request.post?
return invalid_json? || validation_errors?(webhook)
end
false
super || (request.post? && validation_errors?(webhook))
end

def to_json
Expand Down
37 changes: 32 additions & 5 deletions lib/pact_broker/api/resources/base_resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ module PactBroker
module Api
module Resources
class InvalidJsonError < PactBroker::Error ; end
class NonUTF8CharacterFound < PactBroker::Error ; end

class BaseResource < Webmachine::Resource
include PactBroker::Services
Expand All @@ -39,6 +40,10 @@ def known_methods
super + ["PATCH"]
end

def malformed_request?
content_type_is_json_but_invalid_json_provided?
end

def finish_request
application_context.after_resource&.call(self)
PactBroker.configuration.after_resource.call(self)
Expand Down Expand Up @@ -125,17 +130,32 @@ def params(options = {})
else
@params_with_string_keys ||= JSON.parse(request_body, { symbolize_names: false }.merge(PACT_PARSING_OPTIONS)) #Not load! Otherwise it will try to load Ruby classes.
end
rescue JSON::JSONError => e
raise InvalidJsonError.new("Error parsing JSON - #{e.message}")
rescue StandardError => e
fragment = fragment_before_invalid_utf_8_char

if fragment
raise NonUTF8CharacterFound.new(message("errors.non_utf_8_char_in_request_body", char_number: fragment.length + 1, fragment: fragment))
else
raise InvalidJsonError.new(e.message)
end
end
# rubocop: enable Metrics/CyclomaticComplexity

def fragment_before_invalid_utf_8_char
request_body.each_char.with_index do | char, index |
if !char.valid_encoding?
return index < 100 ? request_body[0...index] : request_body[index-100...index]
end
end
nil
end

def params_with_string_keys
params(symbolize_names: false)
end

def pact_params
@pact_params ||= PactBroker::Pacts::PactParams.from_request request, identifier_from_path
@pact_params ||= PactBroker::Pacts::PactParams.from_request(request, identifier_from_path)
end

def set_json_error_message message
Expand Down Expand Up @@ -192,9 +212,12 @@ def invalid_json?
begin
params
false
rescue NonUTF8CharacterFound => e
set_json_error_message(e.message)
response.headers["Content-Type"] = "application/hal+json;charset=utf-8"
true
rescue StandardError => e
logger.info "Error parsing JSON #{e} - #{request_body}"
set_json_error_message "Error parsing JSON - #{e.message}"
set_json_error_message("#{e.cause ? e.cause.class.name : e.class.name} - #{e.message}")
response.headers["Content-Type"] = "application/hal+json;charset=utf-8"
true
end
Expand Down Expand Up @@ -279,6 +302,10 @@ def validation_errors_for_schema?(schema_to_use = schema, params_to_validate = p
def malformed_request_for_json_with_schema?(schema_to_use = schema, params_to_validate = params)
invalid_json? || validation_errors_for_schema?(schema_to_use, params_to_validate)
end

def content_type_is_json_but_invalid_json_provided?
request.content_type&.include?("json") && any_request_body? && invalid_json?
end
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@ module Resources
class CurrentlyDeployedVersionsForEnvironment < BaseResource
using PactBroker::StringRefinements

def content_types_accepted
[["application/json", :from_json]]
end

def content_types_provided
[["application/hal+json", :to_json]]
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@ module Resources
class CurrentlySupportedVersionsForEnvironment < BaseResource
using PactBroker::StringRefinements

def content_types_accepted
[["application/json", :from_json]]
end

def content_types_provided
[["application/hal+json", :to_json]]
end
Expand Down
22 changes: 8 additions & 14 deletions lib/pact_broker/api/resources/deployed_version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,6 @@ module Resources
class DeployedVersion < BaseResource
include PactBroker::Messages

def initialize
super
@currently_deployed_param = params(default: {})[:currentlyDeployed]
end

def content_types_provided
[
["application/hal+json", :to_json]
Expand All @@ -33,14 +28,6 @@ def resource_exists?
!!deployed_version
end

def malformed_request?
if request.patch?
return invalid_json?
else
false
end
end

def to_json
decorator_class(:deployed_version_decorator).new(deployed_version).to_json(decorator_options)
end
Expand Down Expand Up @@ -73,7 +60,14 @@ def policy_record

private

attr_reader :currently_deployed_param
# can't use ||= with a potentially nil value
def currently_deployed_param
if defined?(@currently_deployed_param)
@currently_deployed_param
else
@currently_deployed_param = params(default: {})[:currentlyDeployed]
end
end

def process_currently_deployed_param
if currently_deployed_param == false
Expand Down
6 changes: 1 addition & 5 deletions lib/pact_broker/api/resources/environment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,7 @@ def resource_exists?
end

def malformed_request?
if request.put? && environment
invalid_json? || validation_errors_for_schema?(schema, params.merge(uuid: uuid))
else
false
end
super || (request.put? && environment && validation_errors_for_schema?(schema, params.merge(uuid: uuid)))
end

def from_json
Expand Down
6 changes: 1 addition & 5 deletions lib/pact_broker/api/resources/environments.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,7 @@ def post_is_create?
end

def malformed_request?
if request.post?
invalid_json? || validation_errors_for_schema?(schema, params.merge(uuid: uuid))
else
false
end
super || (request.post? && validation_errors_for_schema?(schema, params.merge(uuid: uuid)))
end

def create_path
Expand Down
7 changes: 2 additions & 5 deletions lib/pact_broker/api/resources/pact.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,9 @@ def is_conflict?
potential_duplicate_pacticipants?(pact_params.pacticipant_names) || merge_conflict || disallowed_modification?
end


def malformed_request?
if request.patch? || request.put?
invalid_json? || contract_validation_errors?(Contracts::PutPactParamsContract.new(pact_params), pact_params)
else
false
end
super || ((request.patch? || request.really_put?) && contract_validation_errors?(Contracts::PutPactParamsContract.new(pact_params), pact_params))
end

def resource_exists?
Expand Down
5 changes: 1 addition & 4 deletions lib/pact_broker/api/resources/pact_webhooks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,7 @@ def resource_exists?
end

def malformed_request?
if request.post?
return invalid_json? || validation_errors?(webhook)
end
false
super || (request.post? && validation_errors?(webhook))
end

def validation_errors? webhook
Expand Down
6 changes: 1 addition & 5 deletions lib/pact_broker/api/resources/pacticipant.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,7 @@ def known_methods
end

def malformed_request?
if request.patch? || request.put?
invalid_json? || validation_errors_for_schema?
else
false
end
super || ((request.patch? || request.really_put?) && validation_errors_for_schema?)
end

def from_json
Expand Down
5 changes: 1 addition & 4 deletions lib/pact_broker/api/resources/pacticipant_webhooks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,7 @@ def resource_exists?
end

def malformed_request?
if request.post?
return invalid_json? || webhook_validation_errors?(webhook)
end
false
super || (request.post? && webhook_validation_errors?(webhook))
end

def create_path
Expand Down
5 changes: 1 addition & 4 deletions lib/pact_broker/api/resources/pacticipants.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,7 @@ def allowed_methods
end

def malformed_request?
if request.post?
return invalid_json? || validation_errors_for_schema?
end
false
super || (request.post? && validation_errors_for_schema?)
end

def post_is_create?
Expand Down
16 changes: 10 additions & 6 deletions lib/pact_broker/api/resources/provider_pacts_for_verification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,7 @@ def content_types_accepted
end

def malformed_request?
if (errors = query_schema.call(query)).any?
set_json_validation_error_messages(errors)
true
else
false
end
super || ((request.get? || request.post?) && schema_validation_errors?)
end

def process_post
Expand Down Expand Up @@ -96,6 +91,15 @@ def log_request
def nested_query
@nested_query ||= Rack::Utils.parse_nested_query(request.uri.query)
end

def schema_validation_errors?
if (errors = query_schema.call(query)).any?
set_json_validation_error_messages(errors)
true
else
false
end
end
end
end
end
Expand Down
6 changes: 1 addition & 5 deletions lib/pact_broker/api/resources/publish_contracts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,7 @@ def allowed_methods
end

def malformed_request?
if request.post?
invalid_json? || validation_errors_for_schema?
else
false
end
super || (request.post? && validation_errors_for_schema?)
end

def process_post
Expand Down
14 changes: 8 additions & 6 deletions lib/pact_broker/api/resources/released_version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,6 @@ module Resources
class ReleasedVersion < BaseResource
include PactBroker::Messages

def initialize
super
@currently_supported_param = params(default: {})[:currentlySupported]
end

def content_types_provided
[["application/hal+json", :to_json]]
end
Expand Down Expand Up @@ -63,7 +58,14 @@ def policy_record

private

attr_reader :currently_supported_param
# can't use ||= with a potentially nil value
def currently_supported_param
if defined?(@currently_deployed_param)
@currently_supported_param
else
@currently_supported_param = params(default: {})[:currentlySupported]
end
end

def process_currently_supported_param
if currently_supported_param == false
Expand Down
16 changes: 7 additions & 9 deletions lib/pact_broker/api/resources/verifications.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,7 @@ def resource_exists?
end

def malformed_request?
if request.post?
return true if invalid_json?
errors = verification_service.errors(params)
if !errors.empty?
set_json_validation_error_messages(errors.messages)
return true
end
end
false
super || (request.post? && any_validation_errors?)
end

def create_path
Expand Down Expand Up @@ -91,6 +83,12 @@ def event_context
def verification_params
params(symbolize_names: false).merge("wip" => wip?, "pending" => pending?)
end

def any_validation_errors?
errors = verification_service.errors(params)
set_json_validation_error_messages(errors.messages) if !errors.empty?
!errors.empty?
end
end
end
end
Expand Down
8 changes: 0 additions & 8 deletions lib/pact_broker/api/resources/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,6 @@ def resource_exists?
!!version
end

def malformed_request?
if request.put? && any_request_body?
invalid_json?
else
false
end
end

def from_json
if request.really_put?
handle_request do
Expand Down
5 changes: 1 addition & 4 deletions lib/pact_broker/api/resources/webhook.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,7 @@ def resource_exists?
end

def malformed_request?
if request.put?
return invalid_json? || webhook_validation_errors?(parsed_webhook, uuid)
end
false
super || (request.put? && webhook_validation_errors?(parsed_webhook, uuid))
end

def from_json
Expand Down
6 changes: 4 additions & 2 deletions lib/pact_broker/api/resources/webhook_execution.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,16 @@ def resource_exists?
end

def malformed_request?
if request.post?
if super
true
elsif request.post?
if uuid
false
else
webhook_validation_errors?(webhook)
end
else
super
false
end
end

Expand Down
Loading

0 comments on commit 3addc0c

Please sign in to comment.