<commit_before>module Songkick
  module OAuth2
    class Router

      # Public methods in the namespace take either Rack env objects, or Request
      # objects from Rails/Sinatra and an optional params hash which it then
      # coerces to Rack requests. This is for backward compatibility; originally
      # it only took request objects.

      class << self
        def parse(resource_owner, env)
          error   = detect_transport_error(env)
          request = request_from(env)
          params  = request.params
          auth    = auth_params(env)

          #Password flow not used conflicts with client credentials flow
          #if auth[CLIENT_ID] and auth[CLIENT_ID] != params[CLIENT_ID]
          #  error ||= Provider::Error.new("#{CLIENT_ID} from Basic Auth and request body do not match")
          #end

          params = params.merge(auth)

          if params[GRANT_TYPE]
            error ||= Provider::Error.new('must be a POST request') unless request.post?
            begin
              Provider::Exchange.new(resource_owner, params, error)
            rescue StandardError
              error = Provider::Error.new('Already authorized, invalidate old token first')
            end
          else
            Provider::Authorization.new(resource_owner, params, error)
          end
        end

        def access_token(resource_owner, scopes, env)
          access_token = access_token_from_request(env)
          Provider::AccessToken.new(resource_owner,
                                    scopes,
                                    access_token,
                                    detect_transport_error(env))
        end

        def access_token_from_request(env)
          request = request_from(env)
          params  = request.params
          header  = request.env['HTTP_AUTHORIZATION']

          header && header =~ /^Bearer\s+/ ?
              header.gsub(/^Bearer\s+/, '') :
              params[OAUTH_TOKEN]
        end

        private

        def request_from(env_or_request)
          env = env_or_request.respond_to?(:env) ? env_or_request.env : env_or_request
          env = Rack::MockRequest.env_for(env['REQUEST_URI'] || '', :input => env['RAW_POST_DATA']).merge(env)
          content_type = env['CONTENT_TYPE']
          media_type = content_type.split(/\s*[;,]\s*/, 2).first.downcase if content_type
          if (media_type == 'application/json')
            input = env['rack.input']
            input.rewind
            env.update('rack.request.form_hash' => JSON.parse(input.read), 'rack.request.form_input' => input)
            input.rewind
          end
          Rack::Request.new(env)
        end
<commit_msg>* Fixing POST body being read incorrectly<commit_after>module Songkick
  module OAuth2
    class Router

      # Public methods in the namespace take either Rack env objects, or Request
      # objects from Rails/Sinatra and an optional params hash which it then
      # coerces to Rack requests. This is for backward compatibility; originally
      # it only took request objects.

      class << self
        def parse(resource_owner, env)
          error   = detect_transport_error(env)
          request = request_from(env)
          params  = request.params
          auth    = auth_params(env)

          #Password flow not used conflicts with client credentials flow
          #if auth[CLIENT_ID] and auth[CLIENT_ID] != params[CLIENT_ID]
          #  error ||= Provider::Error.new("#{CLIENT_ID} from Basic Auth and request body do not match")
          #end

          if (request.post?)
            params = JSON.parse(request.body.read)
          end

          params = params.merge(auth)

          if params[GRANT_TYPE]
            error ||= Provider::Error.new('must be a POST request') unless request.post?
            begin
              Provider::Exchange.new(resource_owner, params, error)
            rescue StandardError
              error = Provider::Error.new('Already authorized, invalidate old token first')
            end
          else
            Provider::Authorization.new(resource_owner, params, error)
          end
        end

        def access_token(resource_owner, scopes, env)
          access_token = access_token_from_request(env)
          Provider::AccessToken.new(resource_owner,
                                    scopes,
                                    access_token,
                                    detect_transport_error(env))
        end

        def access_token_from_request(env)
          request = request_from(env)
          params  = request.params
          header  = request.env['HTTP_AUTHORIZATION']

          header && header =~ /^Bearer\s+/ ?
              header.gsub(/^Bearer\s+/, '') :
              params[OAUTH_TOKEN]
        end

        private

        def request_from(env_or_request)
          env = env_or_request.respond_to?(:env) ? env_or_request.env : env_or_request
          env = Rack::MockRequest.env_for(env['REQUEST_URI'] || '', :input => env['RAW_POST_DATA']).merge(env)
          Rack::Request.new(env)
        end

{'fraction_non_alphanumeric': 0.08774345858744836, 'fraction_numerical': 0.0005902026362384419, 'mean_word_length': 1.9506674405107371, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1855341', 'n_tokens_mistral': 1386, 'n_tokens_neox': 1331, 'n_words': 336}