- 修改 clear 方法,移除同步关键字 - 优化 sendTmpMessage 方法,增加日志记录和处理流程 - 更新 GetSeTu 类,改进擦边图片请求的回复文案 -调整 HttpLoggingInterceptor,启用日志输出 - 更新 QQBotApplication 版本号至 1.7.21
217 lines
7.8 KiB
Java
217 lines
7.8 KiB
Java
package com.yutou.okhttp;
|
|
|
|
|
|
import com.yutou.qqbot.utlis.Log;
|
|
import lombok.val;
|
|
import okhttp3.*;
|
|
import okhttp3.internal.http.HttpHeaders;
|
|
import okio.Buffer;
|
|
import okio.BufferedSource;
|
|
|
|
import java.io.IOException;
|
|
import java.nio.charset.Charset;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.logging.Logger;
|
|
|
|
public class HttpLoggingInterceptor implements Interceptor {
|
|
private static final String TAG = "HttpLogging";
|
|
|
|
private static final Charset UTF8 = StandardCharsets.UTF_8;
|
|
|
|
private volatile Level printLevel = Level.BODY;
|
|
private java.util.logging.Level colorLevel;
|
|
private Logger logger;
|
|
|
|
private static boolean prLog;
|
|
|
|
public static void setLog(boolean log) {
|
|
prLog = log;
|
|
}
|
|
|
|
public enum Level {
|
|
NONE, //不打印log
|
|
BASIC, //只打印 请求首行 和 响应首行
|
|
HEADERS, //打印请求和响应的所有 Header
|
|
BODY //所有数据全部打印
|
|
}
|
|
|
|
public HttpLoggingInterceptor(String tag) {
|
|
logger = Logger.getLogger(tag);
|
|
colorLevel = java.util.logging.Level.INFO;
|
|
}
|
|
|
|
public void setPrintLevel(Level level) {
|
|
if (printLevel == null)
|
|
throw new NullPointerException("printLevel == null. Use Level.NONE instead.");
|
|
printLevel = level;
|
|
}
|
|
|
|
public void setColorLevel(java.util.logging.Level level) {
|
|
colorLevel = level;
|
|
}
|
|
|
|
private void log(String message) {
|
|
//logger.log(colorLevel, message);
|
|
if (prLog) {
|
|
// Log.getDynamicLogger(TAG).info(message);
|
|
System.out.println(message);
|
|
}
|
|
//Log.e(TAG,message);
|
|
}
|
|
|
|
@Override
|
|
public Response intercept(Chain chain) throws IOException {
|
|
Request request = chain.request();
|
|
if (request.body() != null && request.body().contentLength() == 0) {
|
|
val headers = request.headers();
|
|
request = chain.call().request().newBuilder()
|
|
.headers(headers)
|
|
.build();
|
|
}
|
|
if (printLevel == Level.NONE) {
|
|
return chain.proceed(request);
|
|
}
|
|
|
|
//请求日志拦截
|
|
logForRequest(request, chain.connection());
|
|
|
|
//执行请求,计算请求时间
|
|
long startNs = System.nanoTime();
|
|
Response response;
|
|
try {
|
|
response = chain.proceed(request);
|
|
} catch (Exception e) {
|
|
log("<-- HTTP FAILED: " + e);
|
|
throw e;
|
|
}
|
|
long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs);
|
|
|
|
//响应日志拦截
|
|
return logForResponse(response, tookMs);
|
|
}
|
|
|
|
private void logForRequest(Request request, Connection connection) throws IOException {
|
|
boolean logBody = (printLevel == Level.BODY);
|
|
boolean logHeaders = (printLevel == Level.BODY || printLevel == Level.HEADERS);
|
|
RequestBody requestBody = request.body();
|
|
boolean hasRequestBody = requestBody != null;
|
|
Protocol protocol = connection != null ? connection.protocol() : Protocol.HTTP_1_1;
|
|
|
|
try {
|
|
String requestStartMessage = "--> " + request.method() + ' ' + request.url() + ' ' + protocol;
|
|
log(requestStartMessage);
|
|
|
|
if (logHeaders) {
|
|
if (hasRequestBody) {
|
|
if (requestBody.contentType() != null) {
|
|
log("\tContent-Type: " + requestBody.contentType());
|
|
}
|
|
if (requestBody.contentLength() != -1) {
|
|
log("\tContent-Length: " + requestBody.contentLength());
|
|
}
|
|
}
|
|
Headers headers = request.headers();
|
|
for (int i = 0, count = headers.size(); i < count; i++) {
|
|
String name = headers.name(i);
|
|
if (!"Content-Type".equalsIgnoreCase(name) && !"Content-Length".equalsIgnoreCase(name)) {
|
|
log("\t" + name + ": " + headers.value(i));
|
|
}
|
|
}
|
|
|
|
log(" ");
|
|
if (logBody && hasRequestBody) {
|
|
if (isPlaintext(requestBody.contentType())) {
|
|
bodyToString(request);
|
|
} else {
|
|
log("\tbody: maybe [binary body], omitted!");
|
|
}
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
logger.log(java.util.logging.Level.WARNING, e.getMessage(), e);
|
|
} finally {
|
|
log("--> END " + request.method());
|
|
}
|
|
}
|
|
|
|
private Response logForResponse(Response response, long tookMs) {
|
|
Response.Builder builder = response.newBuilder();
|
|
Response clone = builder.build();
|
|
ResponseBody responseBody = clone.body();
|
|
boolean logBody = (printLevel == Level.BODY);
|
|
boolean logHeaders = (printLevel == Level.BODY || printLevel == Level.HEADERS);
|
|
|
|
try {
|
|
log("<-- " + clone.code() + ' ' + clone.message() + ' ' + clone.request().url() + " (" + tookMs + "ms)");
|
|
if (logHeaders) {
|
|
Headers headers = clone.headers();
|
|
for (int i = 0, count = headers.size(); i < count; i++) {
|
|
log("\t" + headers.name(i) + ": " + headers.value(i));
|
|
}
|
|
log(" ");
|
|
if (logBody && HttpHeaders.hasBody(clone)) {
|
|
if (responseBody == null) return response;
|
|
|
|
if (isPlaintext(responseBody.contentType())) {
|
|
BufferedSource source = responseBody.source();
|
|
source.request(Long.MAX_VALUE); // 请求整个流
|
|
Buffer buffer = source.buffer();
|
|
|
|
Charset charset = getCharset(responseBody.contentType());
|
|
String body = buffer.clone().readString(charset);
|
|
log("\tbody:" + body);
|
|
} else {
|
|
log("\tbody: maybe [binary body], omitted!");
|
|
}
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
logger.log(java.util.logging.Level.WARNING, e.getMessage(), e);
|
|
} finally {
|
|
log("<-- END HTTP");
|
|
}
|
|
return response;
|
|
}
|
|
|
|
private static Charset getCharset(MediaType contentType) {
|
|
Charset charset = contentType != null ? contentType.charset(UTF8) : UTF8;
|
|
if (charset == null) charset = UTF8;
|
|
return charset;
|
|
}
|
|
|
|
/**
|
|
* Returns true if the body in question probably contains human readable text. Uses a small sample
|
|
* of code points to detect unicode control characters commonly used in binary file signatures.
|
|
*/
|
|
private static boolean isPlaintext(MediaType mediaType) {
|
|
if (mediaType == null) return false;
|
|
if (mediaType.type() != null && mediaType.type().equals("text")) {
|
|
return true;
|
|
}
|
|
String subtype = mediaType.subtype();
|
|
if (subtype != null) {
|
|
subtype = subtype.toLowerCase();
|
|
if (subtype.contains("x-www-form-urlencoded") || subtype.contains("json") || subtype.contains("xml") || subtype.contains("html")) //
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private void bodyToString(Request request) {
|
|
try {
|
|
Request copy = request.newBuilder().build();
|
|
RequestBody body = copy.body();
|
|
if (body == null) return;
|
|
Buffer buffer = new Buffer();
|
|
body.writeTo(buffer);
|
|
Charset charset = getCharset(body.contentType());
|
|
log("\tbody:" + buffer.readString(charset));
|
|
// 重置请求体以确保后续处理不受影响
|
|
buffer.clear();
|
|
} catch (Exception e) {
|
|
logger.log(java.util.logging.Level.WARNING, e.getMessage(), e);
|
|
}
|
|
}
|
|
}
|