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

parser->FeedRecvData解析http头如果遇到错误,会直接hio_close,但仍返回code200 #666

Open
KivinChiu opened this issue Jan 7, 2025 · 5 comments

Comments

@KivinChiu
Copy link

KivinChiu commented Jan 7, 2025

比如发起请求的url参数中含有未编码的中文字符时等parser错误的情况时,返回的状态码仍是200,但连接已被关闭。

 nfeed = parser->FeedRecvData(data, len);
  if (nfeed != len) {
     hloge("[%s:%d] http parse error: %s,data: [%s]", ip, port, parser->StrError(parser->GetError()),data);
     error = ERR_PARSE;
    //只能在此处增加强制返回400,但这个位置显然不是最佳实践,我研究了许久也没找到应该在哪里设置
     resp->status_code = HTTP_STATUS_BAD_REQUEST;
     SendHttpStatusResponse(HTTP_STATUS_BAD_REQUEST);
     return -1;
 }
@ithewei
Copy link
Owner

ithewei commented Jan 8, 2025

解析出错的情况下,就会直接close,为什么还会返回响应?

@KivinChiu
Copy link
Author

KivinChiu commented Jan 8, 2025

解析出错的情况下,就会直接close,为什么还会返回响应?

我的意思是解析出错了关闭连接没有问题,但应该告诉客户端BAD_REQUEST而不是OK。
站在客户端或api访问者的角度。使用curl或编写代码访问libhv服务器的api接口,如果不小心对querystring的参数没有进行urlencode,那么得到的结果是statucode 200,表明连接成功了,但实际上连接被关闭了,会有些莫名奇妙。这种情况服务器应该返回BAD_REQUEST而不是200,告诉访问者出错了而不是成功。否则开发人员会认为是服务端接口的问题,前后端两边打架,很难调试。
问题可能出在httpparser阶段,FeedRecvData里可以设置error,但这个error并没有应用到响应中,如果这个阶段出错也应该使用status_code来响应,先响应400 BAD_REQUEST,再hio_close。
我是使用libhv的httpclient访问的,得到的状态码是200,也可能是libhv的http的状态码默认是200,连接被服务器主动关闭的情况下没有更新状态值?我回头用curl模拟一下看看是什么结果。

@KivinChiu
Copy link
Author

KivinChiu commented Jan 8, 2025

使用libhv的httpclient代码如下:

HttpClient cli;
HttpRequest req;
req.method = HTTP_GET;
req.url = "http://127.0.0.1:8080/test?name=张三";//此处“张三”未进行urlencode
HttpResponse resp;
int ret = cli.send(&req, &resp);
if(ret==0){
	printf("status_code:%d",resp.status_code);
	//此请求显示成功,并且status_code值为200,但实际上连接被关闭了,并没有响应体
	//我不知道是httpclient的问题(可能未处理服务器主动关闭的情况?)
	//还是服务端的问题(错误的响应了状态码200?),
}

@KivinChiu
Copy link
Author

问题已经确认,httpclient使用了HttpResponse类,这个类的Init方法status_code默认是HTTP_STATUS_OK,而httpclient初始化后直到服务器返回状态码才会更新,如果服务器直接关闭连接则httpclient类不会更新这个值,并且没有处理error的情况,导致http_client_exec即没返回error码,状态也是200

@KivinChiu
Copy link
Author

我在herr.h中增加了一个名为F(-1022, SERVERCLOSED, "server closed") 的定义。然后在http_client_exec函数中初始化response指针时,强行设置了status_code为110(随便定义的)状态。然后在客户关闭返回时判断没有其它错误而状态码仍是110时判定服务器意外关闭了连接,返回ERROR_SERVERCLOSED,问题解决。作者应该有更好的方法。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants