diff --git a/lib/tracking_middleware.rb b/lib/tracking_middleware.rb index bee3a63..d664736 100644 --- a/lib/tracking_middleware.rb +++ b/lib/tracking_middleware.rb @@ -48,25 +48,11 @@ class TrackingMiddleware Sentry.capture_exception(e) if defined?(Sentry) end - source_image = request.params["src"] - case source_image - when nil + if request.params["src"].nil? headers = {} headers["Content-Type"] = "image/png" headers["Content-Length"] = TRACKING_PIXEL.bytesize.to_s [200, headers, [TRACKING_PIXEL]] - when /\Ahttps?:\/\// - response = Postal::HTTP.get(source_image, timeout: 3) - return [404, {}, ["Not found"]] unless response[:code] == 200 - - headers = {} - headers["Content-Type"] = response[:headers]["content-type"]&.first - headers["Last-Modified"] = response[:headers]["last-modified"]&.first - headers["Cache-Control"] = response[:headers]["cache-control"]&.first - headers["Etag"] = response[:headers]["etag"]&.first - headers["Content-Length"] = response[:body].bytesize.to_s - [200, headers, [response[:body]]] - else [400, {}, ["Invalid/missing source image"]] end diff --git a/spec/lib/tracking_middleware_spec.rb b/spec/lib/tracking_middleware_spec.rb new file mode 100644 index 0000000..0335892 --- /dev/null +++ b/spec/lib/tracking_middleware_spec.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +require "rails_helper" +require "rack/test" + +RSpec.describe TrackingMiddleware do + include Rack::Test::Methods + + let(:inner_app) { ->(_env) { [200, {}, ["inner"]] } } + let(:app) { described_class.new(inner_app) } + + let(:server) { create(:server) } + let(:message) do + MessageFactory.incoming(server) do |_msg, mail| + mail.html_part = Mail::Part.new do + content_type "text/html; charset=UTF-8" + body "
hi" + end + end + end + + def track_headers + { "HTTP_X_POSTAL_TRACK_HOST" => "1" } + end + + describe "GET /img/:server_token/:message_token (open tracking pixel)" do + before do + get "/img/#{server.token}/#{message.token}", {}, track_headers + end + + it "returns the tracking pixel PNG" do + expect(last_response.status).to eq 200 + expect(last_response.headers["Content-Type"]).to eq "image/png" + expect(last_response.body.bytesize).to be > 0 + end + + it "records a load for the message" do + # Re-fetch the message so loads are read fresh from the DB. + reloaded = server.message_db.message(message.id) + expect(reloaded.loads.size).to eq 1 + end + end + + describe "GET /img/:server_token/:message_token?src=