Spec -- ZLink HTTP Client For .NET¶
사용법 중심 문서는 사용자 가이드를 본다. 언어 중립 공통 계약은 공통 spec이 정본이며, 이 문서는 공통 계약에 대한 .NET 고유 편차와 구현 매핑만 기술한다. 공개 계약의 기준은 공통 spec과 이 언어별 spec이다.
src/Zlink.HttpClient/**의 공개 타입과Zlink.HttpClient.UnitTests회귀 테스트는 구현이 그 계약을 지키는지 검증한다.
1. 목적¶
Zlink.HttpClient는 .NET에서 HTTP request를 보내기 위한 별도 client-side 산출물이다.
JSON 전용 client가 아니라 일반 HTTP client이며 zlink fluent builder 스타일로
System.Net.Http의 낮은 수준 설정을 흡수한다. typed 경로
(Body(dto)/Async<T>()/Fetch<T>())는 그 위에 얹은 편의 계층이다.
이 client는 Zlink.Framework.Contracts의 오류·codec 계약을 참조하며
Zlink.Framework server runtime assembly를 참조하지 않는다. 이는 .NET의 package
분할이며, 공통 의존 방향은 01 범위와 아키텍처 §1.3가 소유한다.
HTTP codec registry는 serializer 등록만 처리한다. 등록할 contentType에는 parameter가 없는
ASCII type/subtype을 사용한다. Registry는 앞뒤 SP와 TAB을 제거하고 ASCII 대문자를 소문자로
바꾼 canonical media type을 key로 사용한다.
HTTP response의 Content-Type은 registration 입력과 경계가 다르다. HTTP 규칙에 따라 charset
같은 parameter를 먼저 분리한 뒤, parameter가 없는 media type을 소문자로 바꾸어 canonical key를
찾는다. 따라서 application/json; charset=utf-8처럼 정상적인 parameter가 있는 response도
application/json serializer를 사용한다.
같은 extension이 IZlinkStreamCodecRegistration도 구현하더라도 STREAM descriptor는 무시한다.
HTTP client package는 Stream Connector runtime이나 compression package에 의존하지 않는다.
2. 산출물 경계¶
| 역할 | 위치 | 공개 여부 |
|---|---|---|
| 공개 contract | src/Zlink.HttpClient/*.cs, Contracts/* |
public |
| 공유 오류·codec contract | src/Zlink.Framework.Contracts/Codecs, Errors |
public dependency |
| runtime 구현 | src/Zlink.HttpClient/Runtime/* |
internal |
| 회귀 테스트 | tests/Zlink.HttpClient.UnitTests/* |
private |
| 프로젝트 | Zlink.HttpClient |
public package |
공개 표면에는 SocketsHttpHandler, HttpClientHandler, HttpRequestMessage,
HttpResponseMessage 같은 System.Net.Http 타입을 노출하지 않는다.
3. 공개 타입¶
ZLinkHttpClient— 정적 팩토리에서 만드는 standalone client.Get/Post/Put/Delete/ Patch/Head/Options,IDisposable을 제공한다.ZLinkHttpServerClient— framework 서버가 DI로 제공하는 client. 각 verb는ZLinkHttpServerRequestBuilder를 반환한다.ZLinkHttpClientBuilder—BaseUrl,Codecs,Timeout,DefaultHeader,BasicAuth,BearerToken,MaxResponseBodySize,TrustCertificateFile,ClientCertificateFile,FollowRedirects,Retry,Cookies,Proxy,ProxyBasicAuth,Compression,Build,BuildServer, 그리고 단발 verb shortcut. (Codecs는 framework codec extension 등록 — .NET 고유 확장점, 공통 spec 2.3장 언어 편차)ZLinkHttpRequestBuilder— standalone 표면.Header,Query,Timeout,Body<T>,Body(content, contentType),BodyStream,Form,Multipart,MultipartFile,AsyncRaw,DownloadAsync,Async<T>, decoded body를 직접 반환하는Fetch<T>와 callback overload를 제공한다.ZLinkHttpServerRequestBuilder— standalone 표면을 포함하고 one-wayValueTask Async(CancellationToken cancellationToken = default)를 추가한다. 반환된ValueTask는 비동기 완료와 실패만 전달하며 전송 결과나 admission status를 포함하지 않는다. Shared Spot gate를 반납하고 새 turn에서 이어받는ValueTask<HttpResponse<T>> Yield<T>(CancellationToken cancellationToken = default)도 추가한다. gate 반납이 허용되는SpotWideUser Spot과 Instance Spot에서만 사용한다.IZLinkHttpExecutionScheduler/IZLinkHttpExecutionTurn— DI 통합이 현재 Spot turn을 캡처하고 callback 완료를 원래 실행 줄의 새 turn에 배치하는 공개 주입점이다.RawHttpResponse{Status,Headers,Body}.HttpResponse<T>{Status,Headers,Body,RawBody}.ZLinkHttpMethodenum.
callback overload가 받는 delegate도 공개 계약에 포함한다. 완료 시 error와 response 중 정확히
하나만 null이 아니다.
4. 실행 모델¶
Async<T>는ValueTask<HttpResponse<T>>를 반환하며 Spot turn을 유지한다.Fetch<T>는ValueTask<T>를 반환한다. status와 header가 필요 없는 application sample은 response를 받은 뒤.Body를 꺼내지 않고 이 terminal을 사용한다.
Yield<T>를 제공하지 않는다. Shared Spot gate를 반납하려면
RunIoWorker(...) 안에서 Async<T>를 호출하고 Worker call의 Yield로 기다린다.
- callback overload는 awaitable을 반환하지 않는다. 완료 callback은 요청을 만든 Spot turn의
실행 줄에 새 turn으로 배치한다. standalone client에서는 비동기 완료 문맥에서 직접 호출한다.
- 완료 값을 동기로 꺼내는 blocking terminator는 제공하지 않는다.
5. 전송 의미론¶
기본값·redirect·retry·cookie·압축·인증 스크럽·body 소스 배타 의미론은 공통 spec 2~8장을 따른다. .NET 구현 매핑:
- 네이티브 자동 기능 비활성:
SocketsHttpHandler에서AllowAutoRedirect=false,AutomaticDecompression=None,UseCookies=false— 의미론은 래퍼가 구현. - per-attempt timeout은
HttpClient.Timeout대신 linkedCancellationTokenSource.CancelAfter로 강제(호출자 취소와 timeout을 구분). - TLS:
SslClientAuthenticationOptions(trust 추가 + mTLS). proxy:WebProxy. - 압축 해제: 래퍼가
System.IO.Compression으로 수행.
6. 에러 매핑¶
공통 spec 9장을 따른다. .NET은
ZLinkFrameworkErrorKind를 사용하며 public exception은 재시도 여부를 제공하지 않는다.
- timeout은
DeadlineExceeded와 innerTimeoutException으로 보고한다. 호출자 취소는OperationCanceledException그대로 전파된다.
7. 회귀 테스트 축¶
Zlink.HttpClient.UnitTests의 HttpClientContractTests가 전송 계약 시나리오를 검증한다. chunked 업로드는 managed Linux HttpListener가 chunked 요청
본문을 못 받으므로 raw-socket 서버(RawCaptureServer)로 검증한다.