Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

httpclint 设置 RetryHandler后 重试报空指针 #20

Closed
SnailOfLife opened this issue Jul 8, 2020 · 8 comments · Fixed by #49
Closed

httpclint 设置 RetryHandler后 重试报空指针 #20

SnailOfLife opened this issue Jul 8, 2020 · 8 comments · Fixed by #49
Assignees
Labels
bug Something isn't working

Comments

@SnailOfLife
Copy link

抛出异常:
java.lang.NullPointerException: null
at com.wechat.pay.contrib.apache.httpclient.SignatureExec.execute(SignatureExec.java:48)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)

源码:
if (request.getURI().getHost().endsWith(".mch.weixin.qq.com")) {
return executeWithSignature(route, request, context, execAware);
} else {
return mainExec.execute(route, request, context, execAware);
}
原因
当执行第一次后,request中 uri的host被置为null,再次重试,抛出此异常

@xy-peng xy-peng self-assigned this Jul 8, 2020
@xy-peng xy-peng added the bug Something isn't working label Jul 8, 2020
@ccf0411
Copy link

ccf0411 commented Aug 26, 2020

mark一下

@xy-peng
Copy link
Contributor

xy-peng commented Sep 8, 2020

@SnailOfLife 能贴一下你设置RetryHandler部分的代码吗

@ccf0411
Copy link

ccf0411 commented Oct 13, 2020

@SnailOfLife 能贴一下你设置RetryHandler部分的代码吗

你好,我之前也遇到这个问题,业务场景是发生在,微信支付完成后,立马去做查询操作,此时微信如果在处理中,会返回IO异常,IO异常会自动被org.apache.http.impl.execchain的RetryExec捕获并做重试操作,但是由于第一遍请求时,org.apache.http.impl.execchain里的ProtocolExec中,将uri置空了,所以SignatureExec中,request.getURI().getHost().endsWith(".mch.weixin.qq.com")就会报空指针异常。

@xy-peng
Copy link
Contributor

xy-peng commented Oct 13, 2020

@ccf0411 你好,没太明白具体的场景,还需要你提供更详细的说明

业务场景是发生在,微信支付完成后,立马去做查询操作,此时微信如果在处理中,会返回IO异常

是异步接口?是哪个接口出现的?前面的“完成”是指请求已经发送并收到了微信支付的应答吗?

@SnailOfLife
Copy link
Author

@ccf0411 你好,没太明白具体的场景,还需要你提供更详细的说明

业务场景是发生在,微信支付完成后,立马去做查询操作,此时微信如果在处理中,会返回IO异常

是异步接口?是哪个接口出现的?前面的“完成”是指请求已经发送并收到了微信支付的应答吗?

我是复用连接的时候,连接已失效导致抛出 NoHttpResponseException。这个时候通过httpclient重试机制时用到的。由于默认的重试机制问题,只有在get的时候遇到这个bug,也就是查询操作。

@SnailOfLife
Copy link
Author

@SnailOfLife 能贴一下你设置RetryHandler部分的代码吗

httpClient = builder
.setKeepAliveStrategy(myStrategy)
.evictExpiredConnections()
.setRetryHandler(new MyStandardHttpRequestRetryHandler(3,false))
.setDefaultRequestConfig(defRequestConfig).build();

其中MyStandardHttpRequestRetryHandler 是模仿 StandardHttpRequestRetryHandler 添加 this.idempotentMethods.put("POST", Boolean.TRUE);
但是在正常情况下是复现不出来这个问题的。我调试的时候是将请求超时时间设置为1ms,并重写HttpRequestRetryHandler 中retryRequest 方法始终返回true。才复现了此问题。

线上是因为采用连接池管理复用连接。当选取一个使用过的连接时,有可能已断开抛出NoHttpResponseException 而导致重试的。这个问题只在新的微信分中遇到过。

@xy-peng
Copy link
Contributor

xy-peng commented Oct 13, 2020

String host = request.getURI().getHost();
if(host==null){
host = request.getTarget().toHostString();
}
if (host.endsWith(".mch.weixin.qq.com")) {
return executeWithSignature(route, request, context, execAware);
} else {
return mainExec.execute(route, request, context, execAware);
}

这样改是个办法。

我来重现下,尽快修复这里。确实是个隐患,非常感谢 @SnailOfLife @ccf0411 提供信息。

@xelloss00x
Copy link

@xy-peng 请问下,bug修复了吗

xy-peng added a commit that referenced this issue Apr 7, 2021
… absolute URI (as above) or may be a relative URI.
@xy-peng xy-peng mentioned this issue Apr 7, 2021
xy-peng added a commit that referenced this issue Apr 9, 2021
* fix: #20, use getTarget() instead of getURI(), because the URI may be absolute URI (as above) or may be a relative URI.

* fix: #42,#43 buildMessage()使用toString(entity, utf-8)从entity中获得请求报文

* update version to 0.2.2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants