朋友!的
我在Android应用中收到来自nanohttpd
的偶然和意外的HTTP 400响应。错误遵循特定模式。我已经看了一段时间了,但是我已经到了需要不同角度或其他帮助指向正确方向的地方。
您能否请一看,分享您的想法,甚至直接提出意见和建议?
一些背景
我在我的Android项目中运行nanohttpd
作为临时隔离层(由于服务器端还不够成熟)。我已将Android nanohttpd
中的Service
服务器隔离开来,一旦创建,我就从我的自定义Application
对象开始。这种方式nanohttpd
不受任何特定Activity
生命周期的约束,但可以独立于整个应用程序逻辑和组件生命周期而生存。
问题
现在,(差不多)一切都运行良好和花花公子:我可以启动nanohttpd
并执行一些初始登录请求,我的预期模拟响应甚至可以传递。但是,当我执行第一次“GET”请求时,nanohttpd
会向我发送400 Bad请求状态,但仅限第一次。如果我退出负责特定“GET”请求的Activity
,并再次启动它(从主屏幕),它会以200状态完美地传递预期的有效负载。
我做了什么
我仔细查看了nanohttpd
源代码,试图找出设置此400状态的位置和原因。使用此状态代码并不是很多地方。粗略地说只有here,here和here。由于我没有处理多部分内容,我留下了第一个和第三个“这里”。但是 - 当然 - 我不能为我的生活找到400状态的根本原因,也不会找到导致我状态的确切块。当我调试代码时,一切都很好用。
部分代码
这大致是我的nanohttpd
Service
(MyNanoHttpdService
)的样子:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (ACTION_START.equals(intent.getAction())) {
String errorMessage = null;
if (myNanoHttpd == null) {
String hostUrl = intent.getStringExtra(EXTRA_HOST);
Uri uri = Utils.notEmpty(hostUrl) ? Uri.parse(hostUrl) : Uri.EMPTY;
myNanoHttpd = new MyNanoHttpd(this, uri.getHost(), uri.getPort(), null);
}
if (!myNanoHttpd.isAlive()) {
try {
myNanoHttpd.start();
} catch (IOException e) {
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
e.printStackTrace(printWriter);
errorMessage = stringWriter.toString();
stopSelf();
}
}
final ResultReceiver resultReceiver = intent.getParcelableExtra(EXTRA_RESULT_LISTENER);
if (resultReceiver != null) {
int status = myNanoHttpd.isAlive() ? CODE_SUCCESS : CODE_FAILURE;
Bundle bundle = new Bundle();
bundle.putString(EXTRA_MESSAGE, errorMessage);
resultReceiver.send(status, bundle);
}
}
return Service.START_STICKY;
}
这就是我从自定义Application
对象启动服务的方式,初始化我的客户端状态并获取一些内容:
@Override
public void onCreate() {
super.onCreate();
// Yes, that is a Java 8 Lambda you see there!
MyNanoHttpdService
.start(this, "http://localhost:8080")
.withStartupListener((status, message) -> {
if (status == 0) {
// POST REQUEST: Works like a charm
myNetworkHelper.login();
// GET REQUEST: Always fails on first launch
myNetworkHelper.getContent();
} else {
Log.e("LOG_TAG", "Couldn't start MyNanoHttpd: " + message);
}
});
}
可以安全地假设包装便利代码(.withStartupListener(...)
- 基本上包含了上述ResultReceiver
使用的Service
- 和myNetworkHelper
对象)预期。此外,在制作中,getContent()
来自Activity
或Fragment
,但为了方便起见,我暂时将其移至Application
。
答案 0 :(得分:1)
我可能已找到问题的根本原因,甚至可能是目前的解决方法。
如果我的调查结果正确,则问题是由先前(POST)请求中的未使用数据引起的,从而污染了当前(POST)请求。
NanoHTTPD
代码库中的 This行(NanoHTTPD.HTTPSession.execute()
方法中的标题解析块,在调用任何自定义serve(...)
方法之前 - 第三个&# 34;这里"在上面的问题中)是抛出HTTP 400状态代码的那一行,正如代码所示,"method"
标题没有正确的值。
价值 - 我期望的是" POST"以明文形式 - 被上一个请求中的JSON内容正文部分污染。一旦我意识到这一点,我就尝试使用自定义MyNanoHttpd.serve(IHTTPSession session)
方法使用整个请求正文,如下所示:
@Override
public Response serve(IHTTPSesion session) {
InputStream inputStream = session.getInputStream();
inputStream.skip(inputStream.available());
// or
// inputStream.skip(Long.MAX_VALUE);
// or even
// inputStream.close();
...
}
但是,这并没有奏效,因为我不断得到各种例外。我最后轻轻地修改了NanoHTTPD
代码,安全地关闭了finally
方法的NanoHTTPD.HTTPSession.execute()
块中的输入流。
尽管如此,我还是考虑与NanoHTTPD社区联系,讨论合适且可持续的解决方案。