30 lines
2.6 KiB
Markdown
30 lines
2.6 KiB
Markdown
# 이벤트 상세 API Contract
|
|
|
|
## 1. Request
|
|
`GET {BASE_URL}/api/v2/events/{id}`. 양수 `Int`(지원 iOS에서 signed 64-bit), query/body 없는 `requestPlain`이다. 0/음수는 network 없이 unavailable이다.
|
|
|
|
토큰이 비어 있으면 Authorization을 생략하고, 있으면 `Bearer {token}`을 전달한다. 기존 MoyaProvider의 AuthPlugin/AcceptLanguagePlugin을 유지한다. 기존 `/event`, `/event/popup`의 헤더·경로는 변경하지 않는다.
|
|
|
|
## 2. Response와 판정 순서
|
|
1. HTTP 200이 아닌 응답은 본문과 무관하게 error다. 404나 오류 본문 모양을 추정하지 않는다. 401은 기존 AuthPlugin의 세션/main 처리를 유지한다.
|
|
2. HTTP 200에서 success=false이면 data를 파싱하지 않고 unavailable로 처리한다. localized message의 문구로 분류하지 않는다.
|
|
3. success=true이면 기존 `ApiResponse<EventItem>`의 단일 object가 필요하다. id는 양수이며 요청 ID와 일치해야 한다. thumbnailImageUrl은 required String이다.
|
|
4. data 누락/null/array/깨진 JSON/필수 필드 누락·타입 오류는 response error다. 이전 payload fallback은 없다.
|
|
|
|
```json
|
|
{"success":true,"data":{"id":42,"thumbnailImageUrl":"https://example.invalid/thumb.png","detailImageUrl":null,"popupImageUrl":null,"link":"https://example.invalid/join"},"message":null,"errorProperty":null}
|
|
```
|
|
|
|
```json
|
|
{"success":false,"data":null,"message":"이용할 수 없는 이벤트입니다.","errorProperty":null}
|
|
```
|
|
|
|
기존 EventItem: id Int, thumbnailImageUrl String, detailImageUrl/popupImageUrl/link String?. 새 중복 DTO는 만들지 않는다.
|
|
|
|
## 3. 화면·생명주기 계약
|
|
idle/loading/loaded/unavailable/error를 구별한다. loading은 success/error/transport failure/cancel에서 종료한다. 응답은 main queue에서 반영하고, 첫 응답만 처리한다. loaded 화면 재등장은 요청하지 않는다. 이탈 시 구독 취소와 request identity 무효화로 늦은 응답을 차단한다.
|
|
|
|
unavailable dismissal은 해당 View에서 한 번만 소비한다. 전역 AppState.back을 호출하지 않아 live sheet나 다음 route를 pop하지 않는다. 선택적인 이미지와 링크는 서로 독립적이며 둘 다 없는 유효한 object도 loaded다. popup/thumbnail을 상세 이미지로 대체하지 않는다.
|
|
|
|
참여 URL은 absolute HTTP 또는 HTTPS와 host가 있어야 한다. 빈 값, 상대 경로, scheme-relative, file/javascript/data/기타 custom scheme은 버튼을 숨긴다. canOpenURL 후 사용자의 Button 탭에만 open한다. 다른 화면의 URL 정책은 변경하지 않는다.
|