direct-from-seller-signals.py (5533B)
1 import json 2 3 from fledge.tentative.resources import fledge_http_server_util 4 5 # Script to return hardcoded "Ad-Auction-Signals" header to test header-based 6 # directFromSellerSignals. Requires a "Sec-Ad-Auction-Fetch" header with value 7 # of b"?1" in the request, otherwise returns a 400 response. 8 # 9 # Header "Negative-Test-Option" is used to return some specific hardcoded 10 # response for some negative test cases. 11 # 12 # For all positive test cases, header "Buyer-Origin" is required to be the 13 # origin in perBuyerSignals, otherwise return 400 response. 14 def main(request, response): 15 if fledge_http_server_util.handle_cors_headers_and_preflight(request, response): 16 return 17 18 # Return 400 if there is no "Sec-Ad-Auction-Fetch" header. 19 if ("Sec-Ad-Auction-Fetch" not in request.headers or 20 request.headers.get("Sec-Ad-Auction-Fetch") != b"?1"): 21 response.status = (400, b"Bad Request") 22 response.headers.set(b"Content-Type", b"text/plain") 23 return "Failed to get Sec-Ad-Auction-Fetch in headers or its value is not \"?1\"." 24 25 # Return 500 to test http error. 26 if ("Negative-Test-Option" in request.headers and 27 request.headers.get("Negative-Test-Option") == b"HTTP Error"): 28 response.status = (500, b"Internal Error") 29 response.headers.set(b"Content-Type", b"text/plain") 30 return "Test http error with 500 response." 31 32 # Return 200 but without "Ad-Auction-Signals" header. 33 if ("Negative-Test-Option" in request.headers and 34 request.headers.get("Negative-Test-Option") == b"No Ad-Auction-Signals Header"): 35 response.status = (200, b"OK") 36 response.headers.set(b"Content-Type", b"text/plain") 37 return "Test 200 response without \"Ad-Auction-Signals\" header." 38 39 # Return 200 but with invalid json in "Ad-Auction-Signals" header. 40 if ("Negative-Test-Option" in request.headers and 41 request.headers.get("Negative-Test-Option") == b"Invalid Json"): 42 response.status = (200, b"OK") 43 response.headers.set("Ad-Auction-Signals", b"[{\"adSlot\": \"adSlot\", \"sellerSignals\": \"sellerSignals\", \"auctionSignals\":}]") 44 response.headers.set(b"Content-Type", b"text/plain") 45 return "Test 200 response with invalid json in \"Ad-Auction-Signals\" header." 46 47 # Return 404 but with valid "Ad-Auction-Signals" header to test network error. 48 if ("Negative-Test-Option" in request.headers and 49 request.headers.get("Negative-Test-Option") == b"Network Error"): 50 response.status = (404, b"Not Found") 51 adAuctionSignals = json.dumps( 52 [{ 53 "adSlot": "adSlot", 54 "sellerSignals": "sellerSignals", 55 "auctionSignals": "auctionSignals" 56 }]) 57 response.headers.set("Ad-Auction-Signals", adAuctionSignals) 58 response.headers.set(b"Content-Type", b"text/plain") 59 return "Test network error with 400 response code and valid \"Ad-Auction-Signals\" header." 60 61 # For positive test cases, buyer-origin is required, otherwise return 400. 62 if "Buyer-Origin" not in request.headers: 63 response.status = (400, "Bad Request") 64 response.headers.set(b"Content-Type", b"text/plain") 65 return "Failed to get Buyer-Origin in headers." 66 67 response.status = (200, b"OK") 68 buyerOrigin = request.headers.get("Buyer-Origin").decode('utf-8') 69 70 altResponse = request.headers.get("Alternative-Response") 71 72 if altResponse == b"Overwrite adSlot/1": 73 adAuctionSignals = json.dumps( 74 [{ 75 "adSlot": "adSlot/1", 76 "sellerSignals": "altSellerSignals/1", 77 }]) 78 elif altResponse == b"Overwrite adSlot/1 v2": 79 adAuctionSignals = json.dumps( 80 [{ 81 "adSlot": "adSlot/1", 82 "sellerSignals": "altV2SellerSignals/1", 83 }]) 84 elif altResponse == b"Two keys with same values": 85 adAuctionSignals = json.dumps( 86 [{ 87 "adSlot": "adSlot/1", 88 "sellerSignals": "sameSellerSignals", 89 "auctionSignals": "sameAuctionSignals", 90 "perBuyerSignals": { buyerOrigin: "samePerBuyerSignals" } 91 }, 92 { 93 "adSlot": "adSlot/2", 94 "sellerSignals": "sameSellerSignals", 95 "auctionSignals": "sameAuctionSignals", 96 "perBuyerSignals": { buyerOrigin: "samePerBuyerSignals" } 97 }]) 98 elif altResponse == b"Duplicate adSlot/1": 99 adAuctionSignals = json.dumps( 100 [{ 101 "adSlot": "adSlot/1", 102 "sellerSignals": "firstSellerSignals/1", 103 }, 104 { 105 "adSlot": "adSlot/2", 106 "sellerSignals": "nonDupSellerSignals/2", 107 }, 108 { 109 "adSlot": "adSlot/1", 110 "sellerSignals": "secondSellerSignals/1", 111 }]) 112 else: 113 adAuctionSignals = json.dumps( 114 [{ 115 "adSlot": "adSlot/0", 116 }, 117 { 118 "adSlot": "null", 119 "sellerSignals": "sellerSignals/null", 120 }, 121 { 122 "adSlot": "adSlot/1", 123 "sellerSignals": "sellerSignals/1", 124 }, 125 { 126 "adSlot": "adSlot/2", 127 "auctionSignals": "auctionSignals/2", 128 }, 129 { 130 "adSlot": "adSlot/3", 131 "perBuyerSignals": { buyerOrigin: "perBuyerSignals/3" } 132 }, 133 { 134 "adSlot": "adSlot/4", 135 "sellerSignals": "sellerSignals/4", 136 "auctionSignals": "auctionSignals/4", 137 "perBuyerSignals": { buyerOrigin: "perBuyerSignals/4" } 138 }, 139 { 140 "adSlot": "adSlot/5", 141 "sellerSignals": "sellerSignals/5", 142 "auctionSignals": "auctionSignals/5", 143 "perBuyerSignals": { "mismatchOrigin": "perBuyerSignals/5" } 144 }]) 145 146 response.headers.set("Ad-Auction-Signals", adAuctionSignals) 147 response.headers.set(b"Content-Type", b"text/plain") 148 return