data pipeline 개발
This commit is contained in:
166
Assets/Scripts/UVC/Network/DebounceRequester.cs
Normal file
166
Assets/Scripts/UVC/Network/DebounceRequester.cs
Normal file
@@ -0,0 +1,166 @@
|
||||
using Cysharp.Threading.Tasks;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using UVC.Network;
|
||||
|
||||
namespace AssetsUVC.Network
|
||||
{
|
||||
/// <summary>
|
||||
/// HTTP 요청을 디바운스(debounce) 처리하기 위한 유틸리티 클래스
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 이 클래스는 짧은 시간 내에 반복적으로 발생하는 HTTP 요청을 제어하여
|
||||
/// 마지막 요청만 실행되도록 합니다. 사용자 입력에 따른 API 호출이나
|
||||
/// 실시간 검색과 같이 연속된 요청을 최적화할 때 유용합니다.
|
||||
///
|
||||
/// 기본 사용법:
|
||||
/// <code>
|
||||
/// // DebounceRequester 인스턴스 생성
|
||||
/// var requester = new DebounceRequester();
|
||||
///
|
||||
/// // 연속된 검색 요청 예제
|
||||
/// void OnSearchTextChanged(string searchText)
|
||||
/// {
|
||||
/// requester.Request<SearchResult>(
|
||||
/// 300, // 300ms 디바운스
|
||||
/// "/api/search",
|
||||
/// "get",
|
||||
/// $"{{\"query\": \"{searchText}\"}}",
|
||||
/// null,
|
||||
/// false,
|
||||
/// result => {
|
||||
/// // 검색 결과 처리
|
||||
/// DisplaySearchResults(result);
|
||||
/// }
|
||||
/// );
|
||||
/// }
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
public class DebounceRequester
|
||||
{
|
||||
/// <summary>
|
||||
/// 취소 토큰 소스. 이전 요청을 취소하는 데 사용됩니다.
|
||||
/// </summary>
|
||||
private CancellationTokenSource cts = new CancellationTokenSource();
|
||||
|
||||
/// <summary>
|
||||
/// 취소 토큰을 재설정하여 이전 요청을 취소합니다.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 이 메소드는 새로운 요청이 시작될 때마다 호출되어 이전에 예약된 요청을 취소합니다.
|
||||
/// </remarks>
|
||||
private void resetCancellationToken()
|
||||
{
|
||||
cts.Cancel();
|
||||
cts = new CancellationTokenSource();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DebounceRequester가 사용한 리소스를 해제합니다.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 이 클래스의 사용이 끝나면 항상 Dispose를 호출하여 리소스 누수를 방지해야 합니다.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// // 리소스 해제 예제
|
||||
/// public class SearchManager : IDisposable
|
||||
/// {
|
||||
/// private DebounceRequester requester = new DebounceRequester();
|
||||
///
|
||||
/// public void Dispose()
|
||||
/// {
|
||||
/// requester.Dispose();
|
||||
/// }
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
public void Dispose()
|
||||
{
|
||||
cts.Cancel();
|
||||
cts.Dispose();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 지정된 시간(밀리초) 동안 디바운스된 HTTP 요청을 수행합니다.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">응답 데이터를 변환할 타입</typeparam>
|
||||
/// <param name="milliseconds">디바운스 시간(밀리초)</param>
|
||||
/// <param name="url">요청할 URL (http가 포함되지 않은 경우 Domain과 결합)</param>
|
||||
/// <param name="method">HTTP 메소드 (get, post 등)</param>
|
||||
/// <param name="body">요청 본문으로 전송할 JSON 문자열 (null 가능)</param>
|
||||
/// <param name="header">추가할 헤더 정보 (null 가능)</param>
|
||||
/// <param name="useAuth">인증 토큰 사용 여부</param>
|
||||
/// <param name="action">요청 완료 후 실행할 콜백 함수 (null 가능)</param>
|
||||
/// <remarks>
|
||||
/// 이 메소드는 호출된 후 지정된 밀리초 동안 대기하고, 그 시간 내에 다시 호출되면
|
||||
/// 이전 요청을 취소하고 새로운 타이머를 시작합니다. 디바운스 시간이 경과한 후에만
|
||||
/// 실제 HTTP 요청이 수행됩니다.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// // 실시간 타이핑 검색 예제
|
||||
/// private DebounceRequester searchRequester = new DebounceRequester();
|
||||
///
|
||||
/// public void OnSearchInputChanged(string searchText)
|
||||
/// {
|
||||
/// // 사용자가 타이핑을 멈춘 후 500ms 후에 검색 요청
|
||||
/// searchRequester.Request<List<ProductData>>(
|
||||
/// 500,
|
||||
/// "/api/products/search",
|
||||
/// "get",
|
||||
/// $"{{\"query\": \"{searchText}\"}}",
|
||||
/// null,
|
||||
/// true,
|
||||
/// results => {
|
||||
/// // 검색 결과 UI 업데이트
|
||||
/// UpdateSearchResultsUI(results);
|
||||
/// }
|
||||
/// );
|
||||
/// }
|
||||
///
|
||||
/// // 자동 저장 기능 예제
|
||||
/// private DebounceRequester autoSaveRequester = new DebounceRequester();
|
||||
///
|
||||
/// public void OnDocumentChanged(string documentId, string content)
|
||||
/// {
|
||||
/// // 문서 변경 후 2초 동안 추가 변경이 없으면 저장
|
||||
/// var body = $"{{\"id\": \"{documentId}\", \"content\": \"{content}\"}}";
|
||||
///
|
||||
/// autoSaveRequester.Request<SaveResult>(
|
||||
/// 2000,
|
||||
/// "/api/documents/save",
|
||||
/// "post",
|
||||
/// body,
|
||||
/// null,
|
||||
/// true,
|
||||
/// result => {
|
||||
/// if (result.success) {
|
||||
/// ShowSavedNotification();
|
||||
/// }
|
||||
/// }
|
||||
/// );
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
public void Request<T>(int milliseconds, string url, string method, string body = null, Dictionary<string, string> header = null, bool useAuth = false, Action<T> action = null)
|
||||
{
|
||||
resetCancellationToken();
|
||||
UniTask.Delay(TimeSpan.FromMilliseconds(milliseconds), cancellationToken: cts.Token, ignoreTimeScale: false).ContinueWith(async () =>
|
||||
{
|
||||
if (action != null)
|
||||
{
|
||||
T result = await HttpRequester.Request<T>(url, method, body, header, useAuth);
|
||||
action.Invoke(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
HttpRequester.Request<T>(url, method, body, header, useAuth).Forget();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/UVC/Network/DebounceRequester.cs.meta
Normal file
2
Assets/Scripts/UVC/Network/DebounceRequester.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 84bd91fe0c1db234ea850ff5a747f322
|
||||
@@ -21,13 +21,88 @@ namespace UVC.Network
|
||||
/// 이 클래스는 REST API 호출을 위한 메소드들을 제공합니다.
|
||||
/// GET, POST 요청 및 파일 다운로드를 지원하며 요청/응답 로깅 기능도 포함합니다.
|
||||
/// 요청은 비동기(UniTask)로 처리됩니다.
|
||||
///
|
||||
/// 기본 사용법:
|
||||
/// <code>
|
||||
/// // 도메인 설정
|
||||
/// HttpRequester.Domain = "https://api.example.com";
|
||||
///
|
||||
/// // GET 요청 예제
|
||||
/// var products = await HttpRequester.RequestGet<List<Product>>("/api/products");
|
||||
///
|
||||
/// // POST 요청 예제
|
||||
/// var loginData = new Dictionary<string, object>
|
||||
/// {
|
||||
/// { "username", "user@example.com" },
|
||||
/// { "password", "password123" }
|
||||
/// };
|
||||
/// var response = await HttpRequester.RequestPost<LoginResponse>("/api/login", loginData);
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
public static class HttpRequester
|
||||
public class HttpRequester
|
||||
{
|
||||
/// <summary>
|
||||
/// 기본 도메인 주소입니다.
|
||||
/// </summary>
|
||||
public static string Domain {get; set; } = ""; // Replace with your actual API domain
|
||||
public static string Domain { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Dictionary 형태의 본문을 가진 사용자 정의 HTTP 메소드로 API 요청을 수행합니다.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">응답 데이터를 변환할 타입</typeparam>
|
||||
/// <param name="url">요청할 URL (http가 포함되지 않은 경우 Domain과 결합)</param>
|
||||
/// <param name="method">HTTP 메소드 (get, post, put 등)</param>
|
||||
/// <param name="body">요청 본문으로 전송할 Dictionary 데이터 (null 가능)</param>
|
||||
/// <param name="header">추가할 헤더 정보 (null 가능)</param>
|
||||
/// <param name="useAuth">인증 토큰 사용 여부</param>
|
||||
/// <returns>지정된 타입으로 변환된 응답 데이터</returns>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// // PUT 요청 예제
|
||||
/// public async UniTask<ProductResponse> UpdateProductAsync(int productId, string name, float price)
|
||||
/// {
|
||||
/// var body = new Dictionary<string, object>
|
||||
/// {
|
||||
/// { "id", productId },
|
||||
/// { "name", name },
|
||||
/// { "price", price }
|
||||
/// };
|
||||
///
|
||||
/// return await HttpRequester.Request<ProductResponse>("/api/products", "put", body);
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
public static async UniTask<T> Request<T>(string url, string method, Dictionary<string, object> body = null, Dictionary<string, string> header = null, bool useAuth = false)
|
||||
{
|
||||
return await Request_<T>(url, body == null ? null : JsonHelper.ToJson(body), method, header, useAuth);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 문자열 형태의 본문을 가진 사용자 정의 HTTP 메소드로 API 요청을 수행합니다.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">응답 데이터를 변환할 타입</typeparam>
|
||||
/// <param name="url">요청할 URL (http가 포함되지 않은 경우 Domain과 결합)</param>
|
||||
/// <param name="method">HTTP 메소드 (get, post, put 등)</param>
|
||||
/// <param name="body">요청 본문으로 전송할 JSON 문자열 (null 가능)</param>
|
||||
/// <param name="header">추가할 헤더 정보 (null 가능)</param>
|
||||
/// <param name="useAuth">인증 토큰 사용 여부</param>
|
||||
/// <returns>지정된 타입으로 변환된 응답 데이터</returns>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// // DELETE 요청 예제
|
||||
/// public async UniTask<bool> DeleteResourceAsync(string resourceId)
|
||||
/// {
|
||||
/// string jsonBody = $"{{\"id\": \"{resourceId}\"}}";
|
||||
///
|
||||
/// return await HttpRequester.Request<bool>("/api/resources", "delete", jsonBody);
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
public static async UniTask<T> Request<T>(string url, string method, string body = null, Dictionary<string, string> header = null, bool useAuth = false)
|
||||
{
|
||||
return await Request_<T>(url, body, method, header, useAuth);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Dictionary를 JSON body로 변환하여 POST 요청을 수행합니다.
|
||||
@@ -63,7 +138,7 @@ namespace UVC.Network
|
||||
/// </example>
|
||||
public static async UniTask<T> RequestPost<T>(string url, Dictionary<string, object> body = null, Dictionary<string, string> header = null, bool useAuth = false)
|
||||
{
|
||||
return await Request<T>(url, body, HTTPMethods.Post, header, useAuth);
|
||||
return await Request_<T>(url, body == null ? null : JsonHelper.ToJson(body), "post", header, useAuth);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -88,7 +163,7 @@ namespace UVC.Network
|
||||
/// </example>
|
||||
public static async UniTask<T> RequestPost<T>(string url, string body, Dictionary<string, string> header = null, bool useAuth = false)
|
||||
{
|
||||
return await Request<T>(url, body, HTTPMethods.Post, header, useAuth);
|
||||
return await Request_<T>(url, body, "post", header, useAuth);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -126,26 +201,31 @@ namespace UVC.Network
|
||||
/// </example>
|
||||
public static async UniTask<T> RequestGet<T>(string url, Dictionary<string, object> body = null, Dictionary<string, string> header = null, bool useAuth = false)
|
||||
{
|
||||
return await Request<T>(url, body, HTTPMethods.Get, header, useAuth);
|
||||
return await Request_<T>(url, body == null ? null : JsonHelper.ToJson(body), "get", header, useAuth);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// HTTP 요청을 처리하는 내부 메소드
|
||||
/// </summary>
|
||||
private static async UniTask<T> Request<T>(string url, object body = null, HTTPMethods method = HTTPMethods.Post, Dictionary<string, string> header = null, bool useAuth = false)
|
||||
/// <remarks>
|
||||
/// 이 메소드는 모든 HTTP 요청의 공통 로직을 처리합니다:
|
||||
/// - URL 구성 (Domain과 상대 경로 결합)
|
||||
/// - HTTP 메소드 설정
|
||||
/// - 헤더 설정
|
||||
/// - 요청 로깅
|
||||
/// - 응답 처리 및 역직렬화
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">응답 데이터를 변환할 타입</typeparam>
|
||||
/// <param name="url">요청할 URL</param>
|
||||
/// <param name="body">요청 본문 (JSON 문자열)</param>
|
||||
/// <param name="methodString">HTTP 메소드 문자열</param>
|
||||
/// <param name="header">추가할 헤더 정보</param>
|
||||
/// <param name="useAuth">인증 토큰 사용 여부</param>
|
||||
/// <returns>지정된 타입으로 변환된 응답 데이터</returns>
|
||||
private static async UniTask<T> Request_<T>(string url, string body = null, string methodString = "post", Dictionary<string, string> header = null, bool useAuth = false)
|
||||
{
|
||||
string bodyString = "";
|
||||
if (body != null)
|
||||
{
|
||||
if (body is string)
|
||||
{
|
||||
bodyString = body.ToString();
|
||||
}
|
||||
else if (body is Dictionary<string, object>)
|
||||
{
|
||||
bodyString = JsonHelper.ToJson(body);
|
||||
}
|
||||
}
|
||||
HTTPMethods method = StringToMethod(methodString);
|
||||
|
||||
if (!url.Contains("http")) url = $"{Domain}{url}";
|
||||
|
||||
var request = SelectHTTPRequest(method, url);
|
||||
@@ -165,20 +245,12 @@ namespace UVC.Network
|
||||
headerObject.Add(kvp.Key, kvp.Value);
|
||||
}
|
||||
}
|
||||
HttpLogEntry log = ServerLog.LogHttpRequest(url, method.ToString(), headerObject.ToString(Formatting.None), bodyString, DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"));
|
||||
HttpLogEntry log = ServerLog.LogHttpRequest(url, methodString, headerObject.ToString(Formatting.None), body, DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"));
|
||||
//Debug.Log($"Request APIToken :{AuthService.Instance.Entiti.accessToken}");
|
||||
if (body != null)
|
||||
{
|
||||
if (body is string)
|
||||
{
|
||||
request.UploadSettings.UploadStream =
|
||||
new MemoryStream(Encoding.UTF8.GetBytes(body as string));
|
||||
}
|
||||
else if (body is Dictionary<string, object>)
|
||||
{
|
||||
request.UploadSettings.UploadStream =
|
||||
new MemoryStream(Encoding.UTF8.GetBytes(JsonHelper.ToJson(body)));
|
||||
}
|
||||
request.UploadSettings.UploadStream =
|
||||
new MemoryStream(Encoding.UTF8.GetBytes(body));
|
||||
}
|
||||
//var response = await request.GetFromJsonResultAsync<T>();
|
||||
var response = await request.GetAsStringAsync();
|
||||
@@ -224,7 +296,7 @@ namespace UVC.Network
|
||||
/// </example>
|
||||
public static async UniTask<(T, TimeSpan)> RequestPostWithDuration<T>(string url, Dictionary<string, object> body = null, Dictionary<string, string> header = null, bool useAuth = true)
|
||||
{
|
||||
return await RequestWithDuration<T>(url, body, HTTPMethods.Post, header, useAuth);
|
||||
return await RequestWithDuration<T>(url, body == null ? null : JsonHelper.ToJson(body), "post", header, useAuth);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -256,7 +328,7 @@ namespace UVC.Network
|
||||
/// </example>
|
||||
public static async UniTask<(T, TimeSpan)> RequestPostWithDuration<T>(string url, string body, Dictionary<string, string> header = null, bool useAuth = true)
|
||||
{
|
||||
return await RequestWithDuration<T>(url, body, HTTPMethods.Post, header, useAuth);
|
||||
return await RequestWithDuration<T>(url, body, "post", header, useAuth);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -295,26 +367,31 @@ namespace UVC.Network
|
||||
/// </example>
|
||||
public static async UniTask<(T, TimeSpan)> RequestGetWithDuration<T>(string url, Dictionary<string, object> body = null, Dictionary<string, string> header = null, bool useAuth = true)
|
||||
{
|
||||
return await RequestWithDuration<T>(url, body, HTTPMethods.Get, header, useAuth);
|
||||
return await RequestWithDuration<T>(url, body == null ? null : JsonHelper.ToJson(body), "get", header, useAuth);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// HTTP 요청을 처리하고 처리 시간을 측정하는 내부 메소드
|
||||
/// </summary>
|
||||
private static async UniTask<(T, TimeSpan)> RequestWithDuration<T>(string url, object body = null, HTTPMethods method = HTTPMethods.Post, Dictionary<string, string> header = null, bool useAuth = true)
|
||||
/// <remarks>
|
||||
/// 이 메소드는 모든 성능 측정이 필요한 HTTP 요청의 공통 로직을 처리합니다:
|
||||
/// - 요청 처리 시간 측정
|
||||
/// - URL 구성
|
||||
/// - HTTP 메소드 설정
|
||||
/// - 헤더 설정
|
||||
/// - 요청 로깅
|
||||
/// - 응답 처리 및 역직렬화
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">응답 데이터를 변환할 타입</typeparam>
|
||||
/// <param name="url">요청할 URL</param>
|
||||
/// <param name="body">요청 본문 (JSON 문자열)</param>
|
||||
/// <param name="methodString">HTTP 메소드 문자열</param>
|
||||
/// <param name="header">추가할 헤더 정보</param>
|
||||
/// <param name="useAuth">인증 토큰 사용 여부</param>
|
||||
/// <returns>지정된 타입으로 변환된 응답 데이터와 요청 처리 시간의 튜플</returns>
|
||||
private static async UniTask<(T, TimeSpan)> RequestWithDuration<T>(string url, string body = null, string methodString = "", Dictionary<string, string> header = null, bool useAuth = true)
|
||||
{
|
||||
string bodyString = "";
|
||||
if (body != null)
|
||||
{
|
||||
if (body is string)
|
||||
{
|
||||
bodyString = body.ToString();
|
||||
}
|
||||
else if (body is Dictionary<string, object>)
|
||||
{
|
||||
bodyString = JsonHelper.ToJson(body);
|
||||
}
|
||||
}
|
||||
HTTPMethods method = StringToMethod(methodString);
|
||||
if (!url.Contains("http")) url = $"{Domain}{url}";
|
||||
var request = SelectHTTPRequest(method, url);
|
||||
request.DownloadSettings = new Best.HTTP.Request.Settings.DownloadSettings() { ContentStreamMaxBuffered = 1024 * 1024 * 200 };
|
||||
@@ -334,19 +411,11 @@ namespace UVC.Network
|
||||
//if (useAuth) request.SetHeader("access-token", AuthService.Instance.Entiti.accessToken);
|
||||
if (body != null)
|
||||
{
|
||||
if (body is string)
|
||||
{
|
||||
request.UploadSettings.UploadStream =
|
||||
new MemoryStream(Encoding.UTF8.GetBytes(body as string));
|
||||
}
|
||||
else if (body is Dictionary<string, object>)
|
||||
{
|
||||
request.UploadSettings.UploadStream =
|
||||
new MemoryStream(Encoding.UTF8.GetBytes(JsonHelper.ToJson(body)));
|
||||
}
|
||||
request.UploadSettings.UploadStream =
|
||||
new MemoryStream(Encoding.UTF8.GetBytes(body));
|
||||
}
|
||||
|
||||
HttpLogEntry log = ServerLog.LogHttpRequest(url, method.ToString(), headerObject.ToString(Formatting.None), bodyString, DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"));
|
||||
HttpLogEntry log = ServerLog.LogHttpRequest(url, methodString, headerObject.ToString(Formatting.None), body, DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"));
|
||||
//var response = await request.GetFromJsonResultAsync<T>();
|
||||
var now = DateTime.UtcNow;
|
||||
var response = await request.GetAsStringAsync();
|
||||
@@ -415,7 +484,7 @@ namespace UVC.Network
|
||||
req.DownloadSettings.OnDownloadStarted = null;
|
||||
req.DownloadSettings.OnDownloadProgress = null;
|
||||
req.DownloadSettings.DownloadStreamFactory = null;
|
||||
|
||||
|
||||
switch (req.State)
|
||||
{
|
||||
case HTTPRequestStates.Finished:
|
||||
@@ -463,6 +532,20 @@ namespace UVC.Network
|
||||
/// <summary>
|
||||
/// 다운로드 스트림을 처리하여 파일로 저장합니다.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 이 메소드는 스트림 데이터를 지정된 파일로 저장하며, 다운로드가 완료되거나 중단될 때까지 블로킹 방식으로 데이터를 처리합니다.
|
||||
/// 다운로드에 실패한 경우 (길이가 0인 경우) 빈 파일은 삭제됩니다.
|
||||
/// </remarks>
|
||||
/// <param name="savePath">다운로드한 데이터를 저장할 파일 경로</param>
|
||||
/// <param name="blockingStream">다운로드 콘텐츠 스트림</param>
|
||||
/// <returns>저장된 파일의 크기(바이트)</returns>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// // 내부적으로 Download 메소드에서 사용됩니다
|
||||
/// long fileSize = await UniTask.RunOnThreadPool<long>(() =>
|
||||
/// ConsumeDownloadStream(savePath, downloadStream as BlockingDownloadContentStream));
|
||||
/// </code>
|
||||
/// </example>
|
||||
private static long ConsumeDownloadStream(string savePath, BlockingDownloadContentStream blockingStream)
|
||||
{
|
||||
long len = 0;
|
||||
@@ -502,6 +585,18 @@ namespace UVC.Network
|
||||
/// <summary>
|
||||
/// HTTP 메소드와 URL을 기반으로 적절한 HTTPRequest 객체를 생성합니다.
|
||||
/// </summary>
|
||||
/// <param name="methods">요청에 사용할 HTTP 메소드</param>
|
||||
/// <param name="url">요청할 URL</param>
|
||||
/// <param name="onRequest">요청 완료 시 호출될 콜백 (선택 사항)</param>
|
||||
/// <returns>생성된 HTTPRequest 객체</returns>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// // 내부 사용 예제 (직접 사용하지 않음)
|
||||
/// HTTPRequest request = SelectHTTPRequest(HTTPMethods.Get, "https://api.example.com/data");
|
||||
/// request.SetHeader("Custom-Header", "HeaderValue");
|
||||
/// request.Send();
|
||||
/// </code>
|
||||
/// </example>
|
||||
private static HTTPRequest SelectHTTPRequest(HTTPMethods methods, string url, OnRequestFinishedDelegate onRequest = null)
|
||||
{
|
||||
switch (methods)
|
||||
@@ -518,5 +613,22 @@ namespace UVC.Network
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 문자열 형태의 HTTP 메소드를 Best.HTTP.HTTPMethods 열거형으로 변환합니다.
|
||||
/// </summary>
|
||||
/// <param name="method">변환할 HTTP 메소드 문자열 ("get", "post" 등)</param>
|
||||
/// <returns>해당하는 HTTPMethods 열거형 값</returns>
|
||||
/// <exception cref="ArgumentException">지원하지 않는 HTTP 메소드인 경우 발생</exception>
|
||||
private static HTTPMethods StringToMethod(string method)
|
||||
{
|
||||
return method.ToLower() switch
|
||||
{
|
||||
"get" => HTTPMethods.Get,
|
||||
"post" => HTTPMethods.Post,
|
||||
_ => throw new ArgumentException($"Unsupported HTTP method: {method}"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user