http 请求拦截器before获取不到url
famik opened this issue · 10 comments
struct aop_log
{
bool before(http::request& req, http::response& rep)
{
asio2::detail::ignore_unused(rep);
//printf("aop_log before %s\n", req.method_string().data());
printf("url: %s\n", req.url().get_path().data()); // 打印出来是空的
return true;
}
};
你用的应该是较早的版本了,现在新的版本为了兼容boost,类型已经改了,像下面这样:
bool before(http::web_request& req, http::web_response& rep)
但是不管是老版本的,还是新版本的,实际上目前在http_server中这个web_request并没有填充url,所以是空的。
这个url是用在http client里的:
std::string_view url = R"(http://www.baidu.com/cond?json={"qeury":"name like '%abc%'","id":1})";
http::web_request req = http::make_request(url);
asio2::http_client::execute(req);
此时web_request里面保存了url信息,可以获取到url的各种参数信息。
http server 端基本上通过web_request.target()就能获取到http请求的后面那部分的url,就是请求的target,不过你这个用法到是也有意义,意义就是接口比较统一,我考虑考虑后面要不要加上这个功能,因为加这个功能还需要再拼接url,http收到请求的时候只有target,还要查询出host port等,再拼接成一个完整的url才准确。
发Issues的时候从README.md拷过来改的,没注意看是老版本的代码,实际上我在项目中用的是新版本
我是想把请求和响应的日志在拦截器中统一打印出来
取 target() 可以
我想在after把web_response的status和body打印出来,好像也不行
取 target() 可以 我想在after把web_response的status和body打印出来,好像也不行
rep.result(); 就是取status
response的body通常是打印不了的,因为body分两种:字符串和文件;
server.bind("/", [](http::web_request& req, http::web_response& rep)
{
rep.fill_file(req.target());
}, aop_check{}, http::enable_cache);
像上面这段代码,收到的http请求的target通常是/index.html这种,因此通过调用rep.fill_file函数直接设置了一个文件并响应给客户端,此时rep.body()的内部实际上是个文件句柄,且内部没有做对这个文件句柄的打印操作,无法打印。
如果不是调用的rep.fill_file,而是调用的rep.fill_json这种,向客户端返回一段json内容,那么rep.body()的内部实际上就是一个字符串,此时是可以直接打印的,std::cout << rep.body(); 即可,或者用rep.body().text();可以取出字符串的内容。
取 target() 可以 我想在after把web_response的status和body打印出来,好像也不行
rep.result(); 就是取status response的body通常是打印不了的,因为body分两种:字符串和文件;
server.bind("/", [](http::web_request& req, http::web_response& rep) { rep.fill_file(req.target()); }, aop_check{}, http::enable_cache);像上面这段代码,收到的http请求的target通常是/index.html这种,因此通过调用rep.fill_file函数直接设置了一个文件并响应给客户端,此时rep.body()的内部实际上是个文件句柄,且内部没有做对这个文件句柄的打印操作,无法打印。
如果不是调用的rep.fill_file,而是调用的rep.fill_json这种,向客户端返回一段json内容,那么rep.body()的内部实际上就是一个字符串,此时是可以直接打印的,std::cout << rep.body(); 即可,或者用rep.body().text();可以取出字符串的内容。
问题是在拦截器的after函数里打印rep.result()出来一直是0
body是不是字符串可以通过Content-Type来判断
流程:
- before
- server.bind(...) 的监听函数
- after
你是不是在bind(...)中没有给rep的status赋值?如果没有的话,你在after中打印出来的值就是0。
如果你调用的是rep.fill_file file_json这些函数,他已经自动给status赋值为ok了。
如果你没有调用这些函数,自己给rep填充的内容,那你需要自己给status赋值。
如此:rep.result(http::status::ok);
流程:
- before
- server.bind(...) 的监听函数
- after
你是不是在bind(...)中没有给rep的status赋值?如果没有的话,你在after中打印出来的值就是0。
如果你调用的是rep.fill_file file_json这些函数,他已经自动给status赋值为ok了。
如果你没有调用这些函数,自己给rep填充的内容,那你需要自己给status赋值。
如此:rep.result(http::status::ok);
是用fill_json的,发现是用 rep.defer() 延迟给rep填充的在拦截器after取不到
是用fill_json的,发现是用 rep.defer() 延迟给rep填充的在拦截器after取不到
对哦,是有这个问题,我得思考思考,要不要调整。
流程:
- before
- server.bind(...) 的监听函数
- after
你是不是在bind(...)中没有给rep的status赋值?如果没有的话,你在after中打印出来的值就是0。
如果你调用的是rep.fill_file file_json这些函数,他已经自动给status赋值为ok了。
如果你没有调用这些函数,自己给rep填充的内容,那你需要自己给status赋值。
如此:rep.result(http::status::ok);是用fill_json的,发现是用 rep.defer() 延迟给rep填充的在拦截器after取不到
已经修复了这个问题,在develop分支最新代码。
流程:
- before
- server.bind(...) 的监听函数
- after
你是不是在bind(...)中没有给rep的status赋值?如果没有的话,你在after中打印出来的值就是0。
如果你调用的是rep.fill_file file_json这些函数,他已经自动给status赋值为ok了。
如果你没有调用这些函数,自己给rep填充的内容,那你需要自己给status赋值。
如此:rep.result(http::status::ok);是用fill_json的,发现是用 rep.defer() 延迟给rep填充的在拦截器after取不到
已经修复了这个问题,在develop分支最新代码。
再次修复一个问题:当rep.defer()不是在io_context线程中析构时,会导致after没有在io_context线程中调用的问题。理论上before,bind(...),after都应在io_context线程中被调用。
printf("url: %s\n", req.url().get_path().data()); // 打印出来是空的
此问题也已修复。req.url().get_path(); req.url().get_query(); req.url().get_target(); 等现在均可正常调用
但无法获取client请求的完整URL,如想通过req.url().string()来得到http://yourdomain.com/index.html这种,是得不到的,且难以解决,因为client可能使用的是域名,此时服务端的before after函数中只能获取到服务端监听的地址,无法获取域名,如果从Host头中获取域名并不可靠。