Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for chunked httpclient and httpresponse. #823

Merged
merged 16 commits into from
Jun 30, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
e7e1bb5
Add support for chunked httpclient and chuncked httpresponse.
claudiamurialdo Jun 1, 2023
780baa1
Do not append headers for X-GXOBJECT and X-UA-Compatible.
claudiamurialdo Jun 7, 2023
dc26fbd
Condition content-disposition=inline; filename to reports only.
claudiamurialdo Jun 7, 2023
1ce8bd7
Define new property EOF and method ReadChunk for HttpClient datatype.
claudiamurialdo Jun 15, 2023
8a9872d
Delay adding the header X-SPA-MP until the MasterPageObj is instantia…
claudiamurialdo Jun 16, 2023
ab2cc19
Define method ChunkedStreaming to set chunkedResponse at procedure level
claudiamurialdo Jun 16, 2023
dc171a5
Setup Streaming after httpcontext is initialized
claudiamurialdo Jun 16, 2023
211451d
Remove extra changes in spacing and indentation.
claudiamurialdo Jun 20, 2023
7fa5359
_chunkedResponse condition depends only on TransferEncodingChunked he…
claudiamurialdo Jun 21, 2023
6bc71f9
Merge branch 'master' into http-chunked
claudiamurialdo Jun 21, 2023
5dda8b7
Use BufferOutput instead of the deprecated Buffer property in HttpRes…
claudiamurialdo Jun 21, 2023
21d1014
Merge branch 'http-chunked' of https://github.com/genexuslabs/DotNetC…
claudiamurialdo Jun 21, 2023
21752ba
Remove extra blank lines.
claudiamurialdo Jun 21, 2023
14c0a52
ReceiveData was null when httpclient response is chunked.
claudiamurialdo Jun 26, 2023
b96630a
Access SessionId at the beginning of Streamed https procs o to avoid …
claudiamurialdo Jun 28, 2023
40d2c59
Limit BringSessionStateToLife to .NET Framework.
claudiamurialdo Jun 28, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 23 additions & 6 deletions dotnet/src/dotnetframework/GxClasses/Core/Web/GxHttpServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ public class GxHttpResponse
{
HttpResponse _httpRes;
IGxContext _context;

#if !NETCORE
bool _chunkedResponse;
#endif
public GxHttpResponse(IGxContext context)
{
_context = context;
Expand Down Expand Up @@ -137,8 +139,14 @@ public void AddString( string s)
{
if (Response != null)
{
#if !NETCORE
if (_chunkedResponse)
{
Response.Buffer = false;
}
#endif
Response.Write(s);
}
}
}

public void AddFile( string fileName)
Expand All @@ -150,14 +158,23 @@ public void AddFile( string fileName)
}
public void AppendHeader( string name, string value)
{
if(string.Compare(name, "Content-Disposition", true) == 0)
bool transferEncodingHeader = (name.Equals(HttpHeader.TRANSFER_ENCODING, StringComparison.OrdinalIgnoreCase) && value.Equals(HttpHeaderValue.TRANSFER_ENCODING_CHUNKED, StringComparison.OrdinalIgnoreCase));
#if !NETCORE
if (transferEncodingHeader)
_chunkedResponse = true;
#endif

if (string.Compare(name, "Content-Disposition", true) == 0)
{
value = GXUtil.EncodeContentDispositionHeader(value, _context.GetBrowserType());
}
if (_context!=null)
_context.SetHeader(name, value);
if (!transferEncodingHeader)
{
if (_context != null)
_context.SetHeader(name, value);
}
}

}

public class GxSoapRequest : GxHttpRequest
Expand Down
66 changes: 53 additions & 13 deletions dotnet/src/dotnetframework/GxClasses/Domain/GxHttpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public class GxHttpClient : IGxHttpClient, IDisposable
const int StreamWriterDefaultBufferSize = 1024;
Stream _sendStream;
byte[] _receiveData;
StreamReader _receiveStream;
int _timeout = 30000;
short _statusCode = 0;
string _proxyHost;
Expand Down Expand Up @@ -414,6 +415,9 @@ public void AddHeader(string name, string value)
GXLogging.Error(log, String.Format("Error parsing charset ", value, ex));
}
}
if (name.Equals( HttpHeader.ACCEPT, StringComparison.OrdinalIgnoreCase) && value.Equals(HttpHeaderValue.ACCEPT_SERVER_SENT_EVENT, StringComparison.OrdinalIgnoreCase))
_chunkedResponse = true;

_headers.Set(name, value);
}
public void ClearVariables()
Expand Down Expand Up @@ -675,6 +679,7 @@ HttpResponseMessage ExecuteRequest(string method, string requestUrl, CookieConta
handler.ReceiveDataTimeout = milliseconds;
handler.ReceiveHeadersTimeout = milliseconds;
#endif

using (client = new HttpClient(handler))
{
client.Timeout = milliseconds;
Expand All @@ -697,7 +702,10 @@ HttpResponseMessage ExecuteRequest(string method, string requestUrl, CookieConta
reqStream.Seek(0, SeekOrigin.Begin);
request.Content = new ByteArrayContent(reqStream.ToArray());
setHeaders(request, handler.CookieContainer);
response = client.SendAsync(request).GetAwaiter().GetResult();
if (_chunkedResponse)
response = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).GetAwaiter().GetResult();
else
response = client.SendAsync(request).GetAwaiter().GetResult();
}
}
return response;
Expand Down Expand Up @@ -730,18 +738,27 @@ void ReadReponseContent(HttpResponseMessage response)
charset = String.Empty;
}
}

using (MemoryStream ms = new MemoryStream())
if (_chunkedResponse)
{
stream.CopyTo(ms);
_receiveData = ms.ToArray();
if (_encoding == null)
_encoding = Encoding.UTF8;

_receiveStream = new StreamReader(stream, _encoding);
}
int bytesRead = _receiveData.Length;
GXLogging.Debug(log, "BytesRead " + _receiveData.Length);
if (bytesRead > 0 && !encodingFound)
else
{
_encoding = DetectEncoding(charset, out encodingFound, _receiveData, bytesRead);
}
using (MemoryStream ms = new MemoryStream())
{
stream.CopyTo(ms);
_receiveData = ms.ToArray();
}
int bytesRead = _receiveData.Length;
GXLogging.Debug(log, "BytesRead " + _receiveData.Length);
if (bytesRead > 0 && !encodingFound)
{
_encoding = DetectEncoding(charset, out encodingFound, _receiveData, bytesRead);
}
}
}
catch (IOException ioEx)
{
Expand Down Expand Up @@ -787,7 +804,7 @@ public void Execute(string method, string name)

public void HttpClientExecute(string method, string name)
{
HttpResponseMessage response = null;
response = null;
Byte[] Buffer = new Byte[1024];
_errCode = 0;
_errDescription = string.Empty;
Expand Down Expand Up @@ -868,11 +885,15 @@ public void HttpClientExecute(string method, string name)
_errDescription = "The remote server returned an error: (" + _statusCode + ") " + _statusDescription + ".";
}
ClearSendStream();
GXLogging.DebugSanitized(log, "_responseString " + ToString());
if (!_chunkedResponse)
{
GXLogging.DebugSanitized(log, "_responseString " + ToString());
}
}
NameValueCollection _respHeaders;
private bool disposedValue;

private bool _chunkedResponse;
HttpResponseMessage response;
void LoadResponseHeaders(HttpResponseMessage resp)
{
_respHeaders = new NameValueCollection();
Expand Down Expand Up @@ -1363,6 +1384,25 @@ private Encoding ExtractEncodingFromCharset(string responseText, string regExpP,

public override string ToString()
{
if (_chunkedResponse && _receiveStream != null)
claudiamurialdo marked this conversation as resolved.
Show resolved Hide resolved
{
if (!_receiveStream.EndOfStream)
{
string line= _receiveStream.ReadLine();
if (line != null)
return line;
else
return "EOF";
}
else
{
_receiveStream.Dispose();
_receiveStream = null;
response.Dispose();
response = null;
return "EOF";
}
}
if (_encoding == null)
_encoding = Encoding.UTF8;
if (_receiveData == null)
Expand Down
7 changes: 7 additions & 0 deletions dotnet/src/dotnetframework/GxClasses/Helpers/HttpHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ public class HttpHeader
public static string LAST_MODIFIED = "Last-Modified";
public static string EXPIRES = "Expires";
public static string XGXFILENAME = "x-gx-filename";
internal static string ACCEPT = "Accept";
internal static string TRANSFER_ENCODING = "Transfer-Encoding";
}
internal class HttpHeaderValue
{
internal static string ACCEPT_SERVER_SENT_EVENT = "text/event-stream";
internal static string TRANSFER_ENCODING_CHUNKED = "chunked";
}
[DataContract()]
public class HttpJsonError
Expand Down
6 changes: 1 addition & 5 deletions dotnet/src/dotnetframework/GxClasses/Middleware/GXHttp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1877,10 +1877,9 @@ public void ProcessRequest(HttpContext httpContext)
InitPrivates();
try
{
#if NETCORE
SendHeaders();
string clientid = context.ClientID; //Send clientid cookie (before response HasStarted) if necessary, since UseResponseBuffering is not in .netcore3.0
#endif

bool validSession = ValidWebSession();
if (validSession && IntegratedSecurityEnabled)
validSession = ValidSession();
Expand Down Expand Up @@ -1915,9 +1914,6 @@ public void ProcessRequest(HttpContext httpContext)
context.DispatchAjaxCommands();
}
SetCompression(httpContext);
#if !NETCORE
SendHeaders();
#endif
context.ResponseCommited = true;
}
catch (Exception e)
Expand Down
24 changes: 14 additions & 10 deletions dotnet/src/dotnetframework/GxClasses/Model/GXWebProcedure.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public class GXWebProcedure : GXHttpHandler
protected IReportHandler oldReportHandler;
string outputFileName;
string outputType;
bool fileContentInline;

protected int lineHeight;
protected int Gx_line;
Expand Down Expand Up @@ -115,18 +116,20 @@ protected override void sendCacheHeaders()

private void setOuputFileName()
{
string fileName = GetType().Name;
string fileType = "pdf";
if (!string.IsNullOrEmpty(outputFileName))
if (fileContentInline)
{
fileName = outputFileName;
}
if (!string.IsNullOrEmpty(outputType))
{
fileType = outputType.ToLower();
string fileName = GetType().Name;
string fileType = "pdf";
if (!string.IsNullOrEmpty(outputFileName))
{
fileName = outputFileName;
claudiamurialdo marked this conversation as resolved.
Show resolved Hide resolved
}
if (!string.IsNullOrEmpty(outputType))
{
fileType = outputType.ToLower();
}
context.HttpContext.Response.AddHeader(HttpHeader.CONTENT_DISPOSITION, $"inline; filename={fileName}.{fileType}");
}

context.HttpContext.Response.AddHeader(HttpHeader.CONTENT_DISPOSITION, $"inline; filename={fileName}.{fileType}");
}

public virtual int getOutputType()
Expand All @@ -138,6 +141,7 @@ protected bool initPrinter(String output, int gxXPage, int gxYPage, String iniFi
string idiom;
if (!Config.GetValueOf("LANGUAGE", out idiom))
idiom = "eng";
fileContentInline = true;
claudiamurialdo marked this conversation as resolved.
Show resolved Hide resolved
#if NETCORE
setOuputFileName();
#endif
Expand Down