1717import java .net .http .HttpResponse ;
1818import java .time .Duration ;
1919import java .util .Map ;
20+ import java .util .Objects ;
2021import java .util .Random ;
2122import java .util .logging .Level ;
2223import java .util .logging .Logger ;
24+ import java .util .regex .Pattern ;
2325
2426/**
2527 * An HTTP forwarder that delivers DogStatsD HTTP payloads to a remote endpoint.
@@ -77,12 +79,14 @@ public Telemetry.Snapshot snapshot() {
7779 /** Runs the forwarding loop, delivering queued payloads until the thread is interrupted. */
7880 @ Override
7981 public void run () {
80- try {
81- while ( true ) {
82+ while ( true ) {
83+ try {
8284 runOnce (queue .next ());
85+ } catch (InterruptedException e ) {
86+ return ;
87+ } catch (Exception t ) {
88+ logger .log (Level .SEVERE , "unexpected error in forwarder loop" , t );
8389 }
84- } catch (InterruptedException e ) {
85- return ;
8690 }
8791 }
8892
@@ -98,6 +102,8 @@ public void run() {
98102 * ({@link WhenFull#BLOCK} mode only)
99103 */
100104 public void send (URI url , byte [] payload ) throws InterruptedException {
105+ Objects .requireNonNull (url , "url" );
106+ Objects .requireNonNull (payload , "payload" );
101107 queue .add (new Payload (url , payload ));
102108 telemetry .onEnqueue (payload .length );
103109 }
@@ -193,6 +199,7 @@ void backoff() throws InterruptedException {
193199 * @param data the local-data string, or {@code null} to omit the header
194200 */
195201 public void setLocalData (String data ) {
202+ validateHeaderValue (data );
196203 logger .log (Level .INFO , "using local data: {0}" , data );
197204 localData = data ;
198205 }
@@ -207,7 +214,19 @@ public void setLocalData(String data) {
207214 * @param data the external-data string, or {@code null} to omit the header
208215 */
209216 public void setExternalData (String data ) {
217+ validateHeaderValue (data );
210218 logger .log (Level .INFO , "using external data: {0}" , data );
211219 externalData = data ;
212220 }
221+
222+ private static final Pattern validHeaderValue = Pattern .compile ("[\\ t\\ x20-\\ x7E\\ x80-\\ xFF]*" );
223+
224+ private static void validateHeaderValue (String value ) {
225+ if (value == null ) {
226+ return ;
227+ }
228+ if (!validHeaderValue .matcher (value ).matches ()) {
229+ throw new IllegalArgumentException ("invalid character" );
230+ }
231+ }
213232}
0 commit comments