Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RefererParser::InvalidUriError (issue for builds from 3.4.0-beta1 to 3.5.0-beta1) #531

Closed
GesJeremie opened this issue Sep 29, 2020 · 2 comments
Assignees
Labels
bug Something isn't working

Comments

@GesJeremie
Copy link
Contributor

GesJeremie commented Sep 29, 2020

Edit: We probably want to label this not as a bug but more as enhancement (my bad)

Describe the bug
Sentry is reporting an error for one of our build:

image

Investigation

Bonus

If anyone is running into the same issue and are not able to upgrade at the moment, here's my fix (v3.4.32):

# lib/workarea/ext/freedom_patches/referer_parser.rb
module RefererParser
  class Parser
    #
    # Patched to take in account the new scheme `android-app`.
    #
    # See: https://github.com/snowplow-referer-parser/referer-parser/pull/145/commits/737a892f628347a610e5633d62153c8d6518f4e5
    #
    # The PR above has never been officialy released, therefore the patch.
    #
    def parse(obj)
      url = obj.is_a?(URI) ? obj : URI.parse(obj.to_s)
      
      # This section changed
      if !['android-app', 'http', 'https'].include?(url.scheme)
        raise InvalidUriError.new("Only Android-App, HTTP and HTTPS schemes are supported -- #{url.scheme}")
      end

      data = { :known => false, :uri => url.to_s }

      domain, name_key = domain_and_name_key_for(url)
      if domain and name_key
        referer_data = @name_hash[name_key]
        data[:known] = true
        data[:source] = referer_data[:source]
        data[:medium] = referer_data[:medium]
        data[:domain] = domain

        # Parse parameters if the referer uses them
        if url.query and referer_data[:parameters]
          query_params = CGI.parse(url.query)
          referer_data[:parameters].each do |param|
            # If there is a matching parameter, get the first non-blank value
            if !(values = query_params[param]).empty?
              data[:term] = values.select { |v| v.strip != "" }.first
              break if data[:term]
            end
          end
        end
      end

      data
    rescue URI::InvalidURIError
      raise InvalidUriError.new("Unable to parse URI, not a URI? -- #{obj.inspect}", $!)
    end
  end
end
# test/lib/workarea/ext/freedom_patches/referer_parser_test.rb
# A silly test to sleep well at night
require 'test_helper'

module RefererParser
  class ParserTest < Workarea::TestCase
    def test_parse_android_app_referrers
      referrers = [
        'android-app://com.linkedin.android',
        'android-app://org.telegram.plus',
        'android-app://com.twitter.android'
      ]

      assert_nothing_raised do
        referrers.each do |referrer|
          Parser.new.parse(referrer)
        end
      end
    end
  end
end
# You probably want to override Workarea::CurrentReferrer as well to backport the rescue
# app/controllers/workarea/current_referrer.rb
module Workarea
  module CurrentReferrer
    #
    # Base implementation (workarea-core v3.4.32) is prone
    # to raise an error for `RefererParser::Parser.new.parse(referrer)`
    # which will block the user to be able to checkout properly.
    #
    # @source https://github.com/workarea-commerce/workarea/blob/v3.4.32/core/app/controllers/workarea/current_referrer.rb
    #
    # The latest implementation (workarea-core 3.5.18) mitigates the problem
    # by rescue-ing the attributes.
    #
    # @source https://github.com/workarea-commerce/workarea/blob/v3.5.18/core/lib/workarea/visit.rb#L72
    #
    # I took inspiration from the latest implementation and applied the changes here.
    #
    def current_referrer
      return @current_referrer if defined?(@current_referrer)

      referrer = cookies['workarea_referrer']
      return unless referrer.present?
     
      # This rescue is gold, you don't want the user to reach a 404 during checkout ===> -$$$$
      attributes = RefererParser::Parser.new.parse(referrer) rescue {}

      @current_referrer ||= TrafficReferrer.new(
        attributes.slice(:source, :medium, :uri)
      )
    end
  end
end
@GesJeremie GesJeremie added the bug Something isn't working label Sep 29, 2020
@GesJeremie
Copy link
Contributor Author

After more thinking, we probably want to close this ticket:

  • It's actually not the job of Workarea to fix RefererParser:Parser.new.parse to take in account android-app:// schemes -- Either way fixing it actually just set TrafficReferrer#uri to something like "android-app://org.telegram.plus". Still useful but you know ...

  • New versions behave correctly thanks to the rescue introduced in 3.5.0

  • The only thing worth fixing would be to add the rescue in CurrentReferrer for 3.4 in a patch since it affects Checkout (current tests are not able to surface this bug).

Anyway, sorry for all the noise :)

@bencrouse
Copy link
Contributor

I agree that if this is interrupting checkout, it's worth fixing for v3.4. I've made a note for our next sprint. Thanks for bringing it up!

@tubbo tubbo self-assigned this Oct 6, 2020
tubbo pushed a commit that referenced this issue Oct 6, 2020
Android App URLs have a special `android-app://` scheme that is rejected
by the currently released version of the `referer-parser` gem. The code
in this patch already exists in the master branch of the gem, but this
has not yet been released, and if Android users browse the storefront it
can generate an error when collecting referer information.

WORKAREA-295
Fixes #531
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants