/** Log request headers and body. Consumes request body and returns identical replacement. */ Request logAndReplaceRequest(String name, Request request, Object[] args) throws IOException { log.log(String.format("---> %s %s %s", name, request.getMethod(), request.getUrl())); if (logLevel.ordinal() >= LogLevel.HEADERS.ordinal()) { for (Header header : request.getHeaders()) { log.log(header.toString()); } String bodySize = "no"; TypedOutput body = request.getBody(); if (body != null) { String bodyMime = body.mimeType(); if (bodyMime != null) { log.log("Content-Type: " + bodyMime); } long bodyLength = body.length(); bodySize = bodyLength + "-byte"; if (bodyLength != -1) { log.log("Content-Length: " + bodyLength); } if (logLevel.ordinal() >= LogLevel.FULL.ordinal()) { if (!request.getHeaders().isEmpty()) { log.log(""); } if (!(body instanceof TypedByteArray)) { // Read the entire response body to we can log it and replace the original response request = Utils.readBodyToBytesIfNecessary(request); body = request.getBody(); } byte[] bodyBytes = ((TypedByteArray) body).getBytes(); String bodyCharset = MimeUtil.parseCharset(body.mimeType(), "UTF-8"); log.log(new String(bodyBytes, bodyCharset)); } else if (logLevel.ordinal() >= LogLevel.HEADERS_AND_ARGS.ordinal()) { if (!request.getHeaders().isEmpty()) { log.log("---> REQUEST:"); } for (int i = 0; i < args.length; i++) { log.log("#" + i + ": " + args[i]); } } } log.log(String.format("---> END %s (%s body)", name, bodySize)); } return request; }
/** 同步方法直接返回response对象。异步方法返回{@link ResponseWrapper}对象 */ private Object invokeRequest(RequestIntercept intercept, MethodInfo methodInfo, Object[] args) { String url = null; try { methodInfo.init(); String serverUrl = server.getUrl(); final RequestFilter filter; if (methodInfo.filter != null) { filter = methodInfo.filter.newInstance(); } else { filter = RequestFilter.NONE; } final RequestBuilder builder = new RequestBuilder( serverUrl, filter, methodInfo.callIntercept, methodInfo.appendPath, methodInfo, converter, intercept); builder.bindArgs(args, intercept); filter.onComplite(builder); intercept.onComplite(builder); Request request = builder.build(); url = request.getUrl(); if (!methodInfo.isSynchronous && methodInfo.appendPath) { // If we are executing asynchronously then update the current thread with a useful name. int substrEnd = url.indexOf("?", serverUrl.length()); if (substrEnd == -1) { substrEnd = url.length(); } Thread.currentThread() .setName(THREAD_PREFIX + url.substring(serverUrl.length(), substrEnd)); } if (logLevel.log()) { // Log the request data. request = logAndReplaceRequest("HTTP", request, args); } long start = System.nanoTime(); Response response = clientProvider.get().execute(request); long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start); int statusCode = response.getStatus(); if (logLevel.log()) { // Log the response data. response = logAndReplaceResponse(url, response, elapsedTime); } Type type = methodInfo.responseObjectType; if (statusCode >= 200 && statusCode < 300) { // 2XX == successful request // Caller requested the raw Response object directly. if (type.equals(Response.class)) { if (!methodInfo.isStreaming) { // Read the entire stream and replace with one backed by a byte[]. response = Utils.readBodyToBytesIfNecessary(response); } if (methodInfo.isSynchronous) { return response; } return new ResponseWrapper(response, response); } TypedInput body = response.getBody(); if (body == null) { if (methodInfo.isSynchronous) { return null; } return new ResponseWrapper(response, null); } ExceptionCatchingTypedInput wrapped = new ExceptionCatchingTypedInput(body); try { Object convert = converter.fromBody(wrapped, type); logResponseBody(body, convert); if (methodInfo.isSynchronous) { return convert; } return new ResponseWrapper(response, convert); } catch (ConversionException e) { if (wrapped.threwException()) { throw wrapped.getThrownException(); } response = Utils.replaceResponseBody(response, null); throw HNetError.conversionError(url, response, converter, type, e); } } response = Utils.readBodyToBytesIfNecessary(response); throw HNetError.httpError(url, response, converter, type); } catch (HNetError e) { throw e; } catch (IOException e) { if (logLevel.log()) { logException(e, url); } throw HNetError.networkError(url, e); } catch (Throwable t) { if (logLevel.log()) { logException(t, url); } throw HNetError.unexpectedError(url, t); } finally { if (!methodInfo.isSynchronous) { Thread.currentThread().setName(IDLE_THREAD_NAME); } } }