77import java .io .InputStream ;
88import java .net .ConnectException ;
99import java .net .SocketTimeoutException ;
10+ import java .security .MessageDigest ;
1011import java .time .Duration ;
1112import java .util .HashMap ;
1213import java .util .Map ;
@@ -26,6 +27,53 @@ public abstract class HttpClient {
2627 /** A value indicating whether the client should sleep between automatic request retries. */
2728 boolean networkRetriesSleep = true ;
2829
30+ static String UNAME_HASH = computeUnameHash ();
31+
32+ private static String computeUnameHash () {
33+ String uname = "" ;
34+ try {
35+ uname =
36+ (System .getProperty ("os.name" , "" )
37+ + " "
38+ + System .getProperty ("os.version" , "" )
39+ + " "
40+ + System .getProperty ("os.arch" , "" )
41+ + " "
42+ + System .getProperty ("java.version" , "" )
43+ + " "
44+ + System .getProperty ("java.vendor" , "" )
45+ + " "
46+ + System .getProperty ("java.vm.name" , "" )
47+ + " "
48+ + getHostname ())
49+ .trim ();
50+ } catch (Exception e ) {
51+ // fall through with empty string
52+ }
53+ if (uname .isEmpty ()) {
54+ return "" ;
55+ }
56+ try {
57+ MessageDigest md = MessageDigest .getInstance ("MD5" );
58+ byte [] hashBytes = md .digest (uname .getBytes (java .nio .charset .StandardCharsets .UTF_8 ));
59+ StringBuilder sb = new StringBuilder ();
60+ for (byte b : hashBytes ) {
61+ sb .append (String .format ("%02x" , b ));
62+ }
63+ return sb .toString ();
64+ } catch (Exception e ) {
65+ return "" ;
66+ }
67+ }
68+
69+ private static String getHostname () {
70+ try {
71+ return java .net .InetAddress .getLocalHost ().getHostName ();
72+ } catch (Exception e ) {
73+ return "" ;
74+ }
75+ }
76+
2977 /** Initializes a new instance of the {@link HttpClient} class. */
3078 protected HttpClient () {}
3179
@@ -228,6 +276,10 @@ static String buildXStripeClientUserAgentString(String aiAgent) {
228276 propertyMap .put ("ai_agent" , aiAgent );
229277 }
230278
279+ if (!UNAME_HASH .isEmpty ()) {
280+ propertyMap .put ("source" , UNAME_HASH );
281+ }
282+
231283 return ApiResource .INTERNAL_GSON .toJson (propertyMap );
232284 }
233285
0 commit comments