Skip to content

Commit 69db380

Browse files
claudiamurialdoclaudiamurialdo
andauthored
Unify file download logic to set a configurable User-Agent (#1196)
* Unify file download logic to always set a configurable User-Agent The User-Agent is now consistently applied using the GX_HTTPCLIENT_USER_AGENT environment variable or HTTPCLIENT_USER_AGENT in appsettings.json Affects the following functionalities: Adding an image to a PDF ImageAPI when handling images from a URL Inserting an image from url in the database (GetBinary in GxDataRecord) * Skip adding User-Agent by default for compatibility * Add null checks for collections in HttpClient * Rename constant HTTPCLIENT_USER_AGENT to UserAgentHeader for consistency with the property name * Make reports respect the provided User-Agent header when adding external images to PDFs. --------- Co-authored-by: claudiamurialdo <c.murialdo@globant.com>
1 parent ce86f1f commit 69db380

File tree

8 files changed

+135
-74
lines changed

8 files changed

+135
-74
lines changed

dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportItext8.cs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
using System.IO;
66
using System.Text;
77
using GeneXus;
8+
using GeneXus.Http;
9+
using GeneXus.Utils;
810
using iText.Barcodes;
911
using iText.Html2pdf;
1012
using iText.Html2pdf.Resolver.Font;
@@ -481,16 +483,22 @@ public override void GxDrawBitMap(String bitmap, int left, int top, int right, i
481483
{
482484
if (!Path.IsPathRooted(bitmap))
483485
{
484-
485-
image = new Image(ImageDataFactory.Create(defaultRelativePrepend + bitmap));
486-
if (image == null)
486+
if (PathUtil.IsAbsoluteUrl(bitmap))
487487
{
488-
bitmap = webAppDir + bitmap;
489-
image = new Image(ImageDataFactory.Create(bitmap));
488+
image = new Image(ImageDataFactory.Create(HttpHelper.DownloadFile(bitmap, out _)));
490489
}
491490
else
492491
{
493-
bitmap = defaultRelativePrepend + bitmap;
492+
image = new Image(ImageDataFactory.Create(defaultRelativePrepend + bitmap));
493+
if (image == null)
494+
{
495+
bitmap = webAppDir + bitmap;
496+
image = new Image(ImageDataFactory.Create(bitmap));
497+
}
498+
else
499+
{
500+
bitmap = defaultRelativePrepend + bitmap;
501+
}
494502
}
495503
}
496504
else

dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportPDFPig.cs

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
using Font = System.Drawing.Font;
1717
#endif
1818
using System.IO;
19-
using System.Net.Http;
2019
using System.Text;
2120
using GeneXus;
2221
using UglyToad.PdfPig.Core;
@@ -27,6 +26,9 @@
2726
using static UglyToad.PdfPig.Writer.PdfPageBuilder;
2827
using PageSize = UglyToad.PdfPig.Content.PageSize;
2928
using PdfRectangle = UglyToad.PdfPig.Core.PdfRectangle;
29+
using System.Net;
30+
using GeneXus.Http;
31+
using GeneXus.Utils;
3032

3133
namespace GeneXus.Printer
3234
{
@@ -227,24 +229,34 @@ public override void GxDrawBitMap(string bitmap, int left, int top, int right, i
227229
{
228230
try
229231
{
232+
byte[] imageBytes;
230233
if (!Path.IsPathRooted(bitmap))
231234
{
232-
233-
image = imageType == "jpeg" ? pageBuilder.AddJpeg(File.ReadAllBytes(defaultRelativePrepend + bitmap), position) : pageBuilder.AddPng(File.ReadAllBytes(defaultRelativePrepend + bitmap), position);
234-
if (image == null)
235+
if (PathUtil.IsAbsoluteUrl(bitmap))
235236
{
236-
bitmap = webAppDir + bitmap;
237-
image = imageType == "jpeg" ? pageBuilder.AddJpeg(File.ReadAllBytes(bitmap), position) : pageBuilder.AddPng(File.ReadAllBytes(bitmap), position);
237+
imageBytes = HttpHelper.DownloadFile(bitmap, out _);
238238
}
239239
else
240240
{
241-
bitmap = defaultRelativePrepend + bitmap;
241+
string bitmapPath = Path.Combine(defaultRelativePrepend, bitmap);
242+
if (File.Exists(bitmapPath))
243+
{
244+
imageBytes = File.ReadAllBytes(bitmapPath);
245+
bitmap = bitmapPath;
246+
}
247+
else
248+
{
249+
bitmapPath = Path.Combine(webAppDir, bitmap);
250+
imageBytes = File.ReadAllBytes(bitmapPath);
251+
bitmap = bitmapPath;
252+
}
242253
}
243254
}
244255
else
245256
{
246-
image = imageType == "jpeg" ? pageBuilder.AddJpeg(File.ReadAllBytes(bitmap), position) : pageBuilder.AddPng(File.ReadAllBytes(bitmap), position);
257+
imageBytes = File.ReadAllBytes(bitmap);
247258
}
259+
image = imageType == "jpeg" ? pageBuilder.AddJpeg(imageBytes, position) : pageBuilder.AddPng(imageBytes, position);
248260
}
249261
catch (Exception)
250262
{
@@ -272,17 +284,14 @@ public override void GxDrawBitMap(string bitmap, int left, int top, int right, i
272284
private AddedImage AddImageFromURL(string url, PdfRectangle position)
273285
{
274286
AddedImage image = null;
275-
using (HttpClient httpClient = new HttpClient())
287+
byte[] imageBytes = HttpHelper.DownloadFile(url, out HttpStatusCode statusCode);
288+
try
276289
{
277-
byte[] imageBytes = httpClient.GetByteArrayAsync(url).Result;
278-
try
279-
{
280-
image = pageBuilder.AddJpeg(imageBytes, position);
281-
}
282-
catch (Exception)
283-
{
284-
pageBuilder.AddPng(imageBytes, position);
285-
}
290+
image = pageBuilder.AddJpeg(imageBytes, position);
291+
}
292+
catch (Exception)
293+
{
294+
pageBuilder.AddPng(imageBytes, position);
286295
}
287296
if (image == null)
288297
{

dotnet/src/dotnetframework/GxClasses/Core/GXUtilsCommon.cs

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
#if NETCORE
1616
using Microsoft.AspNetCore.Http;
1717
using GxClasses.Helpers;
18-
using System.Net;
1918
#endif
19+
using System.Net;
2020
using NodaTime;
2121
using NUglify;
2222
using NUglify.Html;
@@ -38,6 +38,11 @@
3838
using GeneXus.Http;
3939
using System.Security;
4040
using System.Net.Http.Headers;
41+
using System.Security.Policy;
42+
using GeneXus.Http.Client;
43+
44+
45+
4146
#if NETCORE
4247
using Image = GeneXus.Drawing.Image;
4348
using GeneXus.Drawing;
@@ -51,6 +56,7 @@
5156
#endif
5257
using System.Net.Http;
5358

59+
5460
namespace GeneXus.Utils
5561
{
5662
public class GxDefaultProps
@@ -5885,21 +5891,18 @@ private static Bitmap BitmapCreateFromStream(string filePathOrUrl)
58855891
Uri uri;
58865892
if (Uri.TryCreate(filePathOrUrl, UriKind.Absolute, out uri) && (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps))
58875893
{
5888-
using (HttpClient httpClient = new HttpClient())
5894+
try
58895895
{
5890-
try
5896+
byte[] data = HttpHelper.DownloadFile(uri.AbsoluteUri, out HttpStatusCode statusCode);
5897+
using (MemoryStream mem = new MemoryStream(data))
58915898
{
5892-
byte[] data = httpClient.GetByteArrayAsync(uri).Result;
5893-
using (MemoryStream mem = new MemoryStream(data))
5894-
{
5895-
return new Bitmap(mem);
5896-
}
5897-
}
5898-
catch
5899-
{
5900-
return null;
5899+
return new Bitmap(mem);
59015900
}
59025901
}
5902+
catch
5903+
{
5904+
return null;
5905+
}
59035906
}
59045907
else
59055908
{
@@ -5917,21 +5920,18 @@ private static Image ImageCreateFromStream(string filePathOrUrl)
59175920
Uri uri;
59185921
if (Uri.TryCreate(filePathOrUrl, UriKind.Absolute, out uri) && (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps))
59195922
{
5920-
using (HttpClient httpClient = new HttpClient())
5923+
try
59215924
{
5922-
try
5923-
{
5924-
byte[] data = httpClient.GetByteArrayAsync(uri).Result;
5925-
using (MemoryStream mem = new MemoryStream(data))
5926-
{
5927-
return Image.FromStream(mem);
5928-
}
5929-
}
5930-
catch
5925+
byte[] data = HttpHelper.DownloadFile(uri.AbsoluteUri, out HttpStatusCode statusCode);
5926+
using (MemoryStream mem = new MemoryStream(data))
59315927
{
5932-
return null;
5928+
return Image.FromStream(mem);
59335929
}
59345930
}
5931+
catch
5932+
{
5933+
return null;
5934+
}
59355935
}
59365936
else
59375937
{

dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,7 @@ public class Preferences
860860
public static string DefaultRewriteFile = "rewrite.config";
861861
const string USE_NAMED_PARAMETERS = "UseNamedParameters";
862862
const string REST_DATES_WITH_MILLIS = "REST_DATES_WITH_MILLIS";
863+
const string UserAgentHeader = "UserAgentHeader";
863864
internal const string YES = "1";
864865
internal const string NO = "0";
865866
static string defaultDatastore;
@@ -875,6 +876,17 @@ internal static string AppMainNamespace
875876
return nameSpace;
876877
}
877878
}
879+
internal static string HttpClientUserAgent
880+
{
881+
get
882+
{
883+
if (Config.GetValueOrEnvironmentVarOf(UserAgentHeader, out string userAgent))
884+
return userAgent;
885+
else
886+
return string.Empty;
887+
}
888+
}
889+
878890
internal static bool IsBeforeConnectEventConfigured()
879891
{
880892

dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2835,6 +2835,7 @@ static public object ConvertToExternal(Type to, Object i)
28352835
}
28362836
return o;
28372837
}
2838+
internal static bool IsNullOrEmpty(IList collection) => collection == null || collection.Count == 0;
28382839
}
28392840
public interface IGxCollectionConverter
28402841
{

dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -158,50 +158,60 @@ private async Task<byte[]> ReceiveDataAsync()
158158
}
159159

160160
private const int POOLED_CONNECTION_LIFETIME_MINUTES = 2;
161+
161162
internal static ConcurrentDictionary<string, HttpClient> _httpClientInstances = new ConcurrentDictionary<string, HttpClient>();
163+
internal static HttpClient GetHttpClientInstance(Uri uri, out bool disposableInstance)
164+
{
165+
return GetHttpClientInstance(uri, 0, null, null, null, null, string.Empty, 0, out disposableInstance);
166+
}
162167
private static HttpClient GetHttpClientInstance(Uri URI, int timeout, ArrayList authCollection, ArrayList authProxyCollection, X509Certificate2Collection certificateCollection, List<string> fileCertificateCollection, string proxyHost, int proxyPort, out bool disposableInstance)
163168
{
169+
HttpClient client;
164170
if (CacheableInstance(authCollection, authProxyCollection))
165171
{
166-
HttpClient value;
167172
disposableInstance = false;
168173
string key = HttpClientInstanceIdentifier(proxyHost, proxyPort, fileCertificateCollection, timeout);
169-
if (_httpClientInstances.TryGetValue(key, out value))
174+
if (_httpClientInstances.TryGetValue(key, out client))
170175
{
171176
GXLogging.Debug(log, $"Getting httpClient cached instance");
172-
return value;
177+
return client;
173178
}
174179
else
175180
{
176181
lock (syncRootHttpInstance)
177182
{
178-
if (_httpClientInstances.TryGetValue(key, out value))
183+
if (_httpClientInstances.TryGetValue(key, out client))
179184
{
180185
GXLogging.Debug(log, $"Getting httpClient cached instance");
181-
return value;
186+
return client;
187+
}
188+
client = new HttpClient(GetHandler(URI, authCollection, authProxyCollection, certificateCollection, proxyHost, proxyPort));
189+
if (timeout != 0)
190+
{
191+
client.Timeout = TimeSpan.FromMilliseconds(timeout);
182192
}
183-
value = new HttpClient(GetHandler(URI, authCollection, authProxyCollection, certificateCollection, proxyHost, proxyPort));
184-
value.Timeout = TimeSpan.FromMilliseconds(timeout);
185-
_httpClientInstances.TryAdd(key, value);
186-
return value;
193+
_httpClientInstances.TryAdd(key, client);
187194
}
188195
}
189196
}
190197
else
191198
{
192199
disposableInstance = true;
193-
return new HttpClient(GetHandler(URI, authCollection, authProxyCollection, certificateCollection, proxyHost, proxyPort));
200+
client = new HttpClient(GetHandler(URI, authCollection, authProxyCollection, certificateCollection, proxyHost, proxyPort));
194201
}
202+
if (!string.IsNullOrEmpty(Preferences.HttpClientUserAgent))
203+
client.DefaultRequestHeaders.UserAgent.ParseAdd(Preferences.HttpClientUserAgent);
204+
return client;
195205
}
196206

197207
private static string HttpClientInstanceIdentifier(string proxyHost, int proxyPort, List<string> fileCertificateCollection, int timeout)
198208
{
199209
bool defaultSslOptions = ServicePointManager.ServerCertificateValidationCallback == null;
200-
if (string.IsNullOrEmpty(proxyHost) && fileCertificateCollection.Count==0 && timeout== DEFAULT_TIMEOUT && defaultSslOptions)
210+
if (string.IsNullOrEmpty(proxyHost) && CollectionUtils.IsNullOrEmpty(fileCertificateCollection) && timeout== DEFAULT_TIMEOUT && defaultSslOptions)
201211
{
202212
return string.Empty;
203213
}
204-
else if (fileCertificateCollection.Count==0)
214+
else if (CollectionUtils.IsNullOrEmpty(fileCertificateCollection))
205215
{
206216
return $"{proxyHost}:{proxyPort}::{timeout}:{defaultSslOptions}";
207217
}
@@ -213,7 +223,7 @@ private static string HttpClientInstanceIdentifier(string proxyHost, int proxyPo
213223

214224
private static bool CacheableInstance(ArrayList authCollection, ArrayList authProxyCollection)
215225
{
216-
return authCollection.Count == 0 && authProxyCollection.Count == 0 && Preferences.SingletonHttpClient();
226+
return CollectionUtils.IsNullOrEmpty(authCollection) && CollectionUtils.IsNullOrEmpty(authProxyCollection) && Preferences.SingletonHttpClient();
217227
}
218228
private static SocketsHttpHandler GetHandler(Uri URI, ArrayList authCollection, ArrayList authProxyCollection, X509Certificate2Collection certificateCollection, string proxyHost, int proxyPort)
219229
{
@@ -239,7 +249,7 @@ private static SocketsHttpHandler GetHandler(Uri URI, ArrayList authCollection,
239249
{
240250
handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
241251
}
242-
if (certificateCollection.Count > 0)
252+
if (!CollectionUtils.IsNullOrEmpty(certificateCollection))
243253
{
244254
if (handler.SslOptions.ClientCertificates == null)
245255
{
@@ -1592,6 +1602,8 @@ static ICredentials getCredentialCache(Uri URI, ArrayList authenticationCollecti
15921602
string sScheme;
15931603
GxAuthScheme auth;
15941604
CredentialCache cc = null;
1605+
if (CollectionUtils.IsNullOrEmpty(authenticationCollection))
1606+
return null;
15951607

15961608
for (int i = 0; i < authenticationCollection.Count; i++)
15971609
{

0 commit comments

Comments
 (0)