-
Notifications
You must be signed in to change notification settings - Fork 116
Feature/http stream #1607 #1608
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| /*---------------------------------------------------------- | ||
| /*---------------------------------------------------------- | ||
| This Source Code Form is subject to the terms of the | ||
| Mozilla Public License, v.2.0. If a copy of the MPL | ||
| was not distributed with this file, You can obtain one | ||
|
|
@@ -199,11 +199,23 @@ public HttpResponseContext Head(HttpRequestContext request) | |
| /// <param name="output">Строка. Имя выходного файла</param> | ||
| /// <returns>HTTPОтвет. Ответ сервера.</returns> | ||
| [ContextMethod("ВызватьHTTPМетод", "CallHTTPMethod")] | ||
| public HttpResponseContext Patch(string method, HttpRequestContext request, string output = null) | ||
| public HttpResponseContext CallHTTPMethod(string method, HttpRequestContext request, string output = null) | ||
| { | ||
| return GetResponse(request, method, output); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Вызвать произвольный HTTP-метод с потоком ответа | ||
| /// </summary> | ||
| /// <param name="method">Строка. Имя метода HTTP</param> | ||
| /// <param name="request">HTTPЗапрос. Данные и заголовки запроса http</param> | ||
| /// <returns>HTTPОтвет. Ответ сервера.</returns> | ||
| [ContextMethod("ВызватьHTTPМетодПоток", "CallHTTPMethodStream")] | ||
| public HttpResponseContext CallHTTPMethodStream(string method, HttpRequestContext request) | ||
| { | ||
| return GetResponse(request, method, null, true); | ||
| } | ||
|
|
||
| private HttpWebRequest CreateRequest(string resource) | ||
| { | ||
| var uriBuilder = new UriBuilder(_hostUri); | ||
|
|
@@ -335,7 +347,7 @@ private static List<Range> ParseRange(string rangeHeader) | |
| return range; | ||
| } | ||
|
|
||
| private HttpResponseContext GetResponse(HttpRequestContext request, string method, string output = null) | ||
| private HttpResponseContext GetResponse(HttpRequestContext request, string method, string output = null, bool rawStream = false) | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. А если просто без дополнительных параметров и методов - отдавать сырой поток в методе ПолучитьТелоКакПоток? так не получается?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Я не разобрался зачем он вообще вчитывается в методах заполнения тела =(
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Может попробовать сделать все-таки? Мне кажется, там не обязательно трогать сетевой поток, если не вызывались методы ПолучитьТелоКакСтроку/ДвоичныеДанные
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Попробовать могу, но точно что то отломиться т.к. сейчас поток для чего то вычитывается в боди... |
||
| { | ||
| var webRequest = CreateRequest(request.ResourceAddress); | ||
| webRequest.AllowAutoRedirect = AllowAutoRedirect; | ||
|
|
@@ -359,7 +371,7 @@ private HttpResponseContext GetResponse(HttpRequestContext request, string metho | |
| throw; | ||
| } | ||
|
|
||
| var responseContext = new HttpResponseContext(response, output); | ||
| var responseContext = new HttpResponseContext(response, output, rawStream); | ||
|
|
||
| return responseContext; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| /*---------------------------------------------------------- | ||
| /*---------------------------------------------------------- | ||
| This Source Code Form is subject to the terms of the | ||
| Mozilla Public License, v.2.0. If a copy of the MPL | ||
| was not distributed with this file, You can obtain one | ||
|
|
@@ -28,18 +28,27 @@ public class HttpResponseContext : AutoContext<HttpResponseContext>, IDisposable | |
| // TODO: Нельзя выделить массив размером больше чем 2GB | ||
| // поэтому функционал сохранения в файл не должен использовать промежуточный буфер _body | ||
| private HttpResponseBody _body; | ||
|
|
||
| private Stream _rawStream; | ||
|
|
||
| private string _defaultCharset; | ||
| private string _filename; | ||
|
|
||
| public HttpResponseContext(HttpWebResponse response) | ||
| public HttpResponseContext(HttpWebResponse response, string dumpToFile, bool rawStream) | ||
| { | ||
| RetrieveResponseData(response, null); | ||
| } | ||
|
|
||
| public HttpResponseContext(HttpWebResponse response, string dumpToFile) | ||
| { | ||
| RetrieveResponseData(response, dumpToFile); | ||
| if (!rawStream) | ||
| { | ||
|
|
||
| RetrieveResponseData(response, dumpToFile); | ||
| } | ||
| else | ||
| { | ||
| StatusCode = (int)response.StatusCode; | ||
| _defaultCharset = response.CharacterSet; | ||
|
|
||
| ProcessHeaders(response.Headers); | ||
| _rawStream = response.GetResponseStream(); | ||
| } | ||
| } | ||
|
Comment on lines
+36
to
52
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. КРИТИЧЕСКАЯ ПРОБЛЕМА: Утечка ресурсов HTTP-ответа. В режиме Примените этот diff для сохранения ссылки на response и его освобождения: + private HttpWebResponse _response;
+
public HttpResponseContext(HttpWebResponse response, string dumpToFile, bool rawStream)
{
if (!rawStream)
{
RetrieveResponseData(response, dumpToFile);
}
else
{
StatusCode = (int)response.StatusCode;
_defaultCharset = response.CharacterSet;
ProcessHeaders(response.Headers);
_rawStream = response.GetResponseStream();
+ _response = response;
}
}Затем обновите метод public void Dispose()
{
+ if (_response != null)
+ {
+ _response.Dispose();
+ _response = null;
+ }
+
if (_body != null)
+ {
_body.Dispose();
+ _body = null;
+ }
}
🤖 Prompt for AI Agents |
||
|
|
||
| private void RetrieveResponseData(HttpWebResponse response, string dumpToFile) | ||
|
|
@@ -151,6 +160,9 @@ public IValue GetBodyAsBinaryData() | |
| [ContextMethod("ПолучитьТелоКакПоток", "GetBodyAsStream")] | ||
| public IValue GetBodyAsStream() | ||
| { | ||
| if(_rawStream != null) | ||
| return new GenericStream(_rawStream, true); | ||
|
|
||
| if (_body == null) | ||
| return ValueFactory.Create(); | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify HttpWebResponse disposal in streaming scenarios.
The streaming implementation looks correct and follows appropriate patterns. The method properly delegates to
GetResponsewithrawStream=trueand hardcodesoutputtonull(which is appropriate for streaming).However, please verify that
HttpWebResponseresources are properly managed when streaming. In the current implementation:HttpResponseContextbut not explicitly stored or disposedGetBodyAsStream(), connections may leakConsider verifying:
GenericStreamproperly disposes the underlying stream (thetrueparameter at HttpResponseContext line 164 suggests it does)HttpResponseContextshould hold a reference to the response and implementIDisposableto ensure cleanup🏁 Script executed:
Length of output: 105523
Length of output: 2006
Length of output: 1861
Length of output: 1327
Length of output: 1530
Store and dispose HttpWebResponse in streaming scenarios to prevent connection leaks.
The streaming implementation has a critical resource leak. In the
CallHTTPMethodStreamcode path:HttpWebResponseobject created at line 364 inGetResponse()is passed toHttpResponseContextbut never stored or disposedHttpResponseContext.Dispose()only disposes_body, ignoring both_rawStreamand the response objectusing(response)to dispose the responseHttpWebResponseobjects leak, exhausting the connection pool—particularly problematic in streaming scenarios where connections are held longerFix: Store the
HttpWebResponseas a private field inHttpResponseContextand dispose it in theDispose()method, similar to how the non-streaming path handles it withusing().