مراية لـ
https://github.com/postalserver/postal.git
تم المزامنة 2026-05-31 04:35:42 +00:00
refactor(tracking): remove unused src image proxy
The /img/<server>/<message> endpoint accepted a src=<url> query parameter and proxied the body of that URL back to the caller. Nothing in the codebase ever produces a src= parameter — the parser only inserts a plain tracking pixel and rewrites href links — so this branch is dead code inherited from the original AppMail import. Drop the src branch: requests with src now return 400. The no-src path that serves the tracking pixel and records loads is unchanged, and a spec covers both the pixel-serving path and the removed branch.
هذا الالتزام موجود في:
71
spec/lib/tracking_middleware_spec.rb
Normal file
71
spec/lib/tracking_middleware_spec.rb
Normal file
@@ -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 "<html><body>hi</body></html>"
|
||||
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=<url> (image proxy)" do
|
||||
let(:attacker_url) { "http://internal.example.com/secret" }
|
||||
|
||||
before do
|
||||
stub_request(:get, attacker_url).to_return(status: 200, body: "internal-secret")
|
||||
end
|
||||
|
||||
it "does not fetch the URL and returns 400" do
|
||||
get "/img/#{server.token}/#{message.token}", { src: attacker_url }, track_headers
|
||||
|
||||
expect(last_response.status).to eq 400
|
||||
expect(WebMock).not_to have_requested(:get, attacker_url)
|
||||
end
|
||||
|
||||
it "does not fetch the URL even when the message token is invalid" do
|
||||
get "/img/#{server.token}/nonexistent", { src: attacker_url }, track_headers
|
||||
|
||||
expect(WebMock).not_to have_requested(:get, attacker_url)
|
||||
end
|
||||
end
|
||||
|
||||
describe "when the track-host header is missing" do
|
||||
it "passes the request through to the inner app untouched" do
|
||||
get "/img/#{server.token}/#{message.token}"
|
||||
expect(last_response.body).to eq "inner"
|
||||
end
|
||||
end
|
||||
end
|
||||
المرجع في مشكلة جديدة
حظر مستخدم