gitlab-org--gitlab-foss/lib/gitlab/middleware/compressed_json.rb

66 lines
1.6 KiB
Ruby

# frozen_string_literal: true
module Gitlab
module Middleware
class CompressedJson
COLLECTOR_PATH = '/api/v4/error_tracking/collector'
MAXIMUM_BODY_SIZE = 200.kilobytes.to_i
def initialize(app)
@app = app
end
def call(env)
if compressed_et_request?(env)
input = extract(env['rack.input'])
if input.length > MAXIMUM_BODY_SIZE
return too_large
end
env.delete('HTTP_CONTENT_ENCODING')
env['CONTENT_LENGTH'] = input.length
env['rack.input'] = StringIO.new(input)
end
@app.call(env)
end
def compressed_et_request?(env)
post_request?(env) &&
gzip_encoding?(env) &&
match_content_type?(env) &&
match_path?(env)
end
def too_large
[413, { 'Content-Type' => 'text/plain' }, ['Payload Too Large']]
end
def relative_url
File.join('', Gitlab.config.gitlab.relative_url_root).chomp('/')
end
def extract(input)
Zlib::GzipReader.new(input).read(MAXIMUM_BODY_SIZE + 1)
end
def post_request?(env)
env['REQUEST_METHOD'] == 'POST'
end
def gzip_encoding?(env)
env['HTTP_CONTENT_ENCODING'] == 'gzip'
end
def match_content_type?(env)
env['CONTENT_TYPE'] == 'application/json' ||
env['CONTENT_TYPE'] == 'application/x-sentry-envelope'
end
def match_path?(env)
env['PATH_INFO'].start_with?((File.join(relative_url, COLLECTOR_PATH)))
end
end
end
end