最近需要在请求体而不是请求头中添加token校验,网上查找资料时碰到了一些预料之外的错误,于是记录下解决办法。
在okhttp3中添加拦截器时有两个方法:addInterceptor和addNetworkInterceptor,如果使用addNetworkInterceptor方法,那么网上的拦截器代码会发生错误。
原因是addNetworkInterceptor在发送请求时会自动添加一些请求头,包括:
- Connection:管理连接的持久性。
- Content-Length:表明请求体的长度。
- Host:指定请求的目标主机。
- User-Agent:标识客户端的类型和版本。
其中Content-Length限制了请求体的长度,如果在修改请求体的json时没有同时修改请求头的Content-Length的话,请求体会被截断报错或因长度不足报错,即使RequestBody会自动计算请求体的长度。
以下为拦截器类和测试类的代码:
//拦截器类
@Component
@Slf4j
public class BodyTokenInterceptor implements Interceptor {
@NotNull
@Override
public Response intercept(okhttp3.Interceptor.Chain chain) throws IOException {
// 获取原始请求
Request originalRequest = chain.request();
// 获取原始请求体
RequestBody originalBody = originalRequest.body();
MediaType mediaType = originalBody.contentType();
Buffer buffer = new Buffer();
originalBody.writeTo(buffer);
String originalBodyString = buffer.readUtf8();
// 修改请求体
JSONObject jsonObject = JSONObject.parseObject(originalBodyString);
jsonObject.put("auth", "token");
RequestBody newBody = RequestBody.create(JSONObject.toJSONString(jsonObject), mediaType);
Request newRequest = originalRequest.newBuilder()
// 修改原请求体长度
// .header("Content-Length", String.valueOf(newBody.contentLength()))
.post(newBody)
.build();
// 继续处理修改后的请求
return chain.proceed(newRequest);
}
}
//测试控制器类
@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {
@PostMapping("/send")
public void send() {
// 创建http客户端
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new BodyTokenInterceptor())
// .addNetworkInterceptor(new BodyTokenInterceptor())
.build();
// 创建json请求体
JSONObject json = new JSONObject();
json.put("aaaa", "aaaaa");
json.put("bbbb", "bbbbb");
okhttp3.RequestBody body = okhttp3.RequestBody.create(json.toString(), MediaType.parse("application/json;charset=utf-8"));
// 创建请求
Request request = new Request.Builder()
.url("http://localhost:8080/test/receive")
.post(body)
.build();
try(Response response = client.newCall(request).execute()) {
JSONObject jsonObject = JSONObject.parseObject(Objects.requireNonNull(response.body()).string());
System.out.println(jsonObject);
} catch (IOException e) {
log.error(e.getMessage());
}
}
@PostMapping("/receive")
public void receive(@RequestBody HashMap<String,Object> body) {
System.out.println(body);
}
}
Comments NOTHING