@@ -56,7 +56,7 @@ public final class ClientSideCookieEventHandler implements HttpHandler {
56
56
private final static ETag SENTINEL_ETAG = new ETag (false , "6b3edc43-20ec-4078-bc47-e965dd76b88a" );
57
57
private final static String SENTINEL_ETAG_VALUE = SENTINEL_ETAG .toString ();
58
58
59
- private final ByteBuffer transparentImage ;
59
+ private final Optional < ByteBuffer > transparentImage ;
60
60
private final IncomingRequestProcessingPool processingPool ;
61
61
private final int sourceIndex ;
62
62
@@ -82,17 +82,23 @@ public final class ClientSideCookieEventHandler implements HttpHandler {
82
82
83
83
private static final ObjectReader EVENT_PARAMETERS_READER = new ObjectMapper (new MincodeFactory ()).reader ();
84
84
85
- public ClientSideCookieEventHandler (final IncomingRequestProcessingPool processingPool , final int sourceIndex ) {
85
+ public ClientSideCookieEventHandler (final IncomingRequestProcessingPool processingPool ,
86
+ final boolean sendEmptyResponse ,
87
+ final int sourceIndex ) {
86
88
this .sourceIndex = sourceIndex ;
87
89
this .processingPool = Objects .requireNonNull (processingPool );
88
90
89
- try {
90
- this .transparentImage = ByteBuffer .wrap (
91
- Resources .toByteArray (Resources .getResource ("transparent1x1.gif" ))
92
- ).asReadOnlyBuffer ();
93
- } catch (final IOException e ) {
94
- // Should throw something more specific than this.
95
- throw new RuntimeException ("Could not load transparent image resource." , e );
91
+ if (sendEmptyResponse ) {
92
+ this .transparentImage = Optional .empty ();
93
+ } else {
94
+ try {
95
+ this .transparentImage = Optional .of (ByteBuffer .wrap (
96
+ Resources .toByteArray (Resources .getResource ("transparent1x1.gif" ))
97
+ ).asReadOnlyBuffer ());
98
+ } catch (final IOException e ) {
99
+ // Should throw something more specific than this.
100
+ throw new RuntimeException ("Could not load transparent image resource." , e );
101
+ }
96
102
}
97
103
}
98
104
@@ -109,17 +115,21 @@ public void handleRequest(final HttpServerExchange exchange) {
109
115
* As a last resort, we try to detect duplicates via the ETag header.
110
116
*/
111
117
exchange .getResponseHeaders ()
112
- .put (Headers .CONTENT_TYPE , "image/gif" )
113
118
.put (Headers .ETAG , SENTINEL_ETAG_VALUE )
114
119
.put (Headers .CACHE_CONTROL , "private, no-cache, proxy-revalidate" )
115
120
.put (Headers .PRAGMA , "no-cache" )
116
121
.put (Headers .EXPIRES , "Fri, 14 Apr 1995 11:30:00 GMT" );
117
122
118
123
// If an ETag is present, this is a duplicate event.
119
124
if (ETagUtils .handleIfNoneMatch (exchange , SENTINEL_ETAG , true )) {
120
- // Default status code what we want: 200 OK.
121
125
// Sending the response before logging the event!
122
- exchange .getResponseSender ().send (transparentImage .slice ());
126
+ // We send either 200 OK or 204 No Content, depending on whether we have the image to send.
127
+ if (transparentImage .isPresent ()) {
128
+ exchange .getResponseSender ().send (transparentImage .get ().slice ());
129
+ } else {
130
+ exchange .setStatusCode (StatusCodes .NO_CONTENT )
131
+ .endExchange ();
132
+ }
123
133
124
134
try {
125
135
logEvent (exchange );
@@ -131,8 +141,8 @@ public void handleRequest(final HttpServerExchange exchange) {
131
141
if (logger .isDebugEnabled ()) {
132
142
logger .debug ("Ignoring duplicate event from {}: {}" , sourceAddress , getFullUrl (exchange ));
133
143
}
134
- exchange .setStatusCode (StatusCodes .NOT_MODIFIED );
135
- exchange .endExchange ();
144
+ exchange .setStatusCode (StatusCodes .NOT_MODIFIED )
145
+ .endExchange ();
136
146
}
137
147
}
138
148
@@ -166,13 +176,12 @@ public DivolteEvent parseRequest() throws IncompleteRequestException {
166
176
final boolean isFirstInSession = queryParamFromExchange (exchange , FIRST_IN_SESSION_QUERY_PARAM ).map (TRUE_STRING ::equals ).orElseThrow (IncompleteRequestException ::new );
167
177
final Instant clientTimeStamp = Instant .ofEpochMilli (queryParamFromExchange (exchange , CLIENT_TIMESTAMP_QUERY_PARAM ).map (ClientSideCookieEventHandler ::tryParseBase36Long ).orElseThrow (IncompleteRequestException ::new ));
168
178
169
- final DivolteEvent event = DivolteEvent .createBrowserEvent (exchange , corrupt , partyId , sessionId , eventId ,
170
- requestTime , clientTimeStamp ,
171
- isNewPartyId , isFirstInSession ,
172
- queryParamFromExchange (exchange , EVENT_TYPE_QUERY_PARAM ),
173
- eventParameterSupplier (exchange ),
174
- browserEventData (exchange , pageViewId ));
175
- return event ;
179
+ return DivolteEvent .createBrowserEvent (exchange , corrupt , partyId , sessionId , eventId ,
180
+ requestTime , clientTimeStamp , isNewPartyId ,
181
+ isFirstInSession ,
182
+ queryParamFromExchange (exchange , EVENT_TYPE_QUERY_PARAM ),
183
+ eventParameterSupplier (exchange ),
184
+ browserEventData (exchange , pageViewId ));
176
185
}
177
186
}
178
187
0 commit comments