Retrofit처럼 요청과 응답의 로그를 찍고 싶었다. Moya는 Plugin을 넣을 수 있었다. 전체 코드는 https://gist.github.com/susemi99/841b2c3935b2028b2162842d479de143 에 있다.
MoyaProvider<API>(plugins: [RequestLoggingPlugin()])
import Foundation import Moya /// 네트워크 호출 결과 로그 표시 final class RequestLoggingPlugin: PluginType { /// API를 보내기 직전에 호출 func willSend(_ request: RequestType, target: TargetType) { guard let httpRequest = request.request else { print("--> invalid request") return } let url = httpRequest.description let method = httpRequest.httpMethod ?? "unknown method" var log = "--> \(method) \(url)\n" log.append("API: \(target)\n") if let headers = httpRequest.allHTTPHeaderFields, !headers.isEmpty { log.append("header: \(headers)\n") } if let body = httpRequest.httpBody, let bodyString = String(bytes: body, encoding: String.Encoding.utf8) { log.append("\(bodyString)\n") } log.append("--> END \(method)") print(log) } /// API Response func didReceive(_ result: Result<Response, MoyaError>, target: TargetType) { switch result { case let .success(response): onSuceed(response, target: target, isFromError: false) case let .failure(error): onFail(error, target: target) } } func onSuceed(_ response: Response, target: TargetType, isFromError: Bool) { let request = response.request let url = request?.url?.absoluteString ?? "nil" let statusCode = response.statusCode var log = "<-- \(statusCode) \(url)\n" log.append("API: \(target)\n") response.response?.allHeaderFields.forEach { log.append("\($0): \($1)\n") } if let reString = String(bytes: response.data, encoding: String.Encoding.utf8) { log.append("\(reString)\n") } log.append("<-- END HTTP (\(response.data.count)-byte body)") print(log) } func onFail(_ error: MoyaError, target: TargetType) { if let response = error.response { onSuceed(response, target: target, isFromError: true) return } var log = "<-- \(error.errorCode) \(target)\n" log.append("\(error.failureReason ?? error.errorDescription ?? "unknown error")\n") log.append("<-- END HTTP") print(log) } }
그러면 이런 식으로 결과가 온다.
--> GET https://api.github.com/users/Moya API: profile("Moya") --> END GET <-- 200 https://api.github.com/users/Moya API: profile("Moya") X-Ratelimit-Reset: 1591437524 x-github-media-type: github.v3; format=json content-security-policy: default-src 'none' Content-Length: 458 x-xss-protection: 1; mode=block Cache-Control: public, max-age=60, s-maxage=60 Last-Modified: Fri, 19 Aug 2016 23:35:09 GMT x-frame-options: deny Accept-Ranges: bytes Status: 200 OK X-GitHub-Request-Id: C5AF:2E51:24D125:2EA4ED:5EDB5AC4 Strict-Transport-Security: max-age=31536000; includeSubdomains; preload Access-Control-Allow-Origin: * X-Ratelimit-Remaining: 59 Vary: Accept, Accept-Encoding, Accept, X-Requested-With, Accept-Encoding Etag: W/"d5d249d1ae6fb1c26fccf32a255109f9" Server: GitHub.com Date: Sat, 06 Jun 2020 08:58:45 GMT access-control-expose-headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset X-Ratelimit-Limit: 60 Content-Encoding: gzip x-content-type-options: nosniff referrer-policy: origin-when-cross-origin, strict-origin-when-cross-origin Content-Type: application/json; charset=utf-8 {"login":"Moya","id":13662162,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEzNjYyMTYy","avatar_url":"https://avatars3.githubusercontent.com/u/13662162?v=4","gravatar_id":"","url":"https://api.github.com/users/Moya","html_url":"https://github.com/Moya","followers_url":"https://api.github.com/users/Moya/followers","following_url":"https://api.github.com/users/Moya/following{/other_user}","gists_url":"https://api.github.com/users/Moya/gists{/gist_id}","starred_url":"https://api.github.com/users/Moya/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Moya/subscriptions","organizations_url":"https://api.github.com/users/Moya/orgs","repos_url":"https://api.github.com/users/Moya/repos","events_url":"https://api.github.com/users/Moya/events{/privacy}","received_events_url":"https://api.github.com/users/Moya/received_events","type":"Organization","site_admin":false,"name":"Moya","company":null,"blog":"","location":null,"email":null,"hireable":null,"bio":null,"twitter_username":null,"public_repos":6,"public_gists":0,"followers":0,"following":0,"created_at":"2015-08-05T15:03:29Z","updated_at":"2016-08-19T23:35:09Z"} <-- END HTTP (1133-byte body)
success 가 아니면 이런 식으로 온다.
--> GET https://api.github.com/users/Moya1234 API: profile("Moya1234") --> END GET <-- 404 https://api.github.com/users/Moya1234 API: profile("Moya1234") Date: Sat, 06 Jun 2020 09:00:12 GMT Server: GitHub.com x-frame-options: deny content-security-policy: default-src 'none' Content-Type: application/json; charset=utf-8 X-Ratelimit-Remaining: 58 x-content-type-options: nosniff x-github-media-type: github.v3; format=json X-GitHub-Request-Id: C62D:3EF3:237173:2DB008:5EDB5B1C x-xss-protection: 1; mode=block access-control-expose-headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset Vary: Accept-Encoding, Accept, X-Requested-With X-Ratelimit-Limit: 60 Access-Control-Allow-Origin: * Strict-Transport-Security: max-age=31536000; includeSubdomains; preload Status: 404 Not Found Content-Encoding: gzip X-Ratelimit-Reset: 1591437524 Content-Length: 113 referrer-policy: origin-when-cross-origin, strict-origin-when-cross-origin {"message":"Not Found","documentation_url":"https://developer.github.com/v3/users/#get-a-single-user"} <-- END HTTP (102-byte body)