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 표면에ValueTask<HttpResponse<T>> Yield<T>(CancellationToken cancellationToken = default)를 추가한다. 동작 의미는 언어별 인터페이스 §1.4와 server 실행 계약을 따른다.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을 사용한다.
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)로 검증한다.