Я столкнулся со следующей проблемой, о которой я понятия не имею, как и почему:
Я написал веб-сервис на C ++. Я также использовал пример для клиента, который должен проверить ответ.
client.cpp
#include <memory>
#include <future>
#include <cstdio>
#include <cstdlib>
#include <restbed>
using namespace std;
using namespace restbed;
void print( const shared_ptr< Response >& response )
{
fprintf( stderr, "*** Response ***\n" );
fprintf( stderr, "Status Code: %i\n", response->get_status_code( ) );
fprintf( stderr, "Status Message: %s\n", response->get_status_message( ).data( ) );
fprintf( stderr, "HTTP Version: %.1f\n", response->get_version( ) );
fprintf( stderr, "HTTP Protocol: %s\n", response->get_protocol( ).data( ) );
for ( const auto header : response->get_headers( ) )
{
fprintf( stderr, "Header '%s' > '%s'\n", header.first.data( ), header.second.data( ) );
}
auto length = response->get_header( "Content-Length", 0 );
Http::fetch( length, response );
fprintf( stderr, "Body: %.*s...\n\n", length, response->get_body( ).data( ) );
}
int main( ){
auto request = make_shared<Request>(
Uri("http://localhost:3030/apps/17?start_date=2017-02-01&end_date=2017-01-31&kpis=foo,bar"));
request->set_header("Accept", "application/json");
request->set_header("Host", "localhost");
auto response = Http::sync(request);
print(response);
auto future = Http::async(request, [](const shared_ptr<Request>, const shared_ptr<Response> response){
fprintf(stderr, "Printing async response\n");
print(response);
});
future.wait();
return EXIT_SUCCESS;
}
И мой сервис передает поток в виде фрагментов (или должен передавать поток в виде фрагментов)
Во-первых, он передает параметры запроса, такие как start_date, end_date и kpis. Во-вторых, запрашиваемые данные передаются в потоковом режиме.
Вот функция stream_result_parameter:
void stream_result_parameter(std::shared_ptr<restbed::Session> session, const Parameter params,
const std::string endpoint, const std::string mime_type)
{
std::stringstream stream;
if(mime_type.compare("application/json") == 0)
{
std::vector<std::string> kpis = params.get_kpis();
stream << "\n{\n"<< "\"result_parameter\":{\n"<< "\"App\":" << params.get_app_id() << ",\n"<< "\"start_date\":" << params.get_start_date() << ",\n"<< "\"end_date\":" << params.get_end_date() << ",\n"<< "\"Kpis\":[";
for(std::vector<std::string>::iterator kpi = kpis.begin(); kpi != kpis.end(); ++kpi)
{
if(kpi == kpis.end()-1)
{
stream << *kpi << "]\n},";
}
else
{
stream << *kpi << ",";
}
}
}
else
{
if(endpoint.compare("app") == 0 )
{
stream << "Called App Endpoint App: "<< std::to_string(params.get_app_id())
<< "\r\nStart Date: "<< params.get_start_date()
<< "\r\nEnd Date: "<< params.get_end_date()
<<"\n";
}
else
{
stream << "Called Cohorts Endpoint App: "<< std::to_string(params.get_app_id())
<< "\r\nStart Date: "<< params.get_start_date()
<< "\r\nEnd Date: "<< params.get_end_date()
<<"\n";
}
}
session->yield(200, "\r"+stream.str()+"\r",
{ { "Content-Length", std::to_string( stream.str().length())},
{ "Content-Type", mime_type },
{ "Connection", "keep-alive" } });
}
Теперь моя проблема возникла после того, как я добавил Content-Length, где он просто останавливается и закрывает диалог между клиентом и им (службой). curl
дает мне следующую ошибку
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 3030 (#0)
> GET /apps/17?start_date=2017-02-01&end_date=2017-01-31&kpis=foo,bar HTTP/1.1
> Host: localhost:3030
> User-Agent: curl/7.54.0
> Accept:text/csv
>
< HTTP/1.1 200 OK
< Connection: keep-alive
< Content-Length: 94
< Content-Type: text/csv
<
* Excess found in a non pipelined read: excess = 2, size = 94, maxdownload = 94, bytecount = 0
Called App Endpoint App: 17
Start Date: Wed. February 1 2017
* Connection #0 to host localhost left intact
End Date: Tue. January 31 2017
Избыток имеет какое-либо отношение к этому?
Наконец, я хочу показать вам вывод моего тестового клиента и curl
если я возьму контент-длина далеко.
вывод client.cpp:
*** Response ***
Status Code: 200
Status Message: OK
HTTP Version: 1.1
HTTP Protocol: HTTP
Header 'Connection' > 'keep-alive'
Header 'Content-Type' > 'application/json'
Body: ...
Printing async response
*** Response ***
Status Code: 200
Status Message: OK
HTTP Version: 1.1
HTTP Protocol: HTTP
Header 'Connection' > 'keep-alive'
Header 'Content-Length' > '64'
Header 'Content-Type' > 'application/json'
Body:
"result_set":{
"i":1,
"j values": [
{"j":1,"kpi_values":[1,1]}...
Но curl
дает мне все, что мне нужно:
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 3030 (#0)
> GET /apps/17?start_date=2017-02-01&end_date=2017-01-31&kpis=foo,bar HTTP/1.1
> Host: localhost:3030
> User-Agent: curl/7.54.0
> Accept:text/csv
>
< HTTP/1.1 200 OK
< Connection: keep-alive
< Content-Type: text/csv
* no chunk, no close, no size. Assume close to signal end
<
Called App Endpoint App: 17
Start Date: Wed. February 1 2017
End Date: Tue. January 31 2017
1,1,1,1
1,2,1,2
1,3,1,3
1,4,1,4
1,5,1,0
1,6,1,1
1,7,1,2
1,8,1,3
1,9,1,4
1,10,1,0
2,1,2,1
2,2,2,2
2,3,2,3
2,4,2,4
2,5,2,0
2,6,2,1
2,7,2,2
2,8,2,3
2,9,2,4
2,10,2,0
(Обратите внимание, что я не хотел копировать 17400 строк, так что это всего лишь часть полного и правильного вывода)
Может быть, я нарушаю какое-то правило или пропускаю что-то другое, но я просто не могу об этом думать. заранее спасибо
Лишнее сообщение исчезло, как только я учел "/r"
s, но ответ все равно отправлен, и больше не может быть фрагментов:
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 3030 (#0)
> GET /apps/17?start_date=2017-02-01&end_date=2017-01-31&kpis=foo,bar HTTP/1.1
> Host: localhost:3030
> User-Agent: curl/7.54.0
> Accept:text/csv
>
< HTTP/1.1 200 OK
< Connection: keep-alive
< Content-Length: 96
< Content-Type: text/csv
<
Called App Endpoint App: 17
Start Date: Wed. February 1 2017
End Date: Tue. January 31 2017
* Connection #0 to host localhost left intact
Как только ответ получен, ваша заявка закончится.
auto future = Http::async(request, [](const shared_ptr<Request>, const shared_ptr<Response> response){
fprintf(stderr, "Printing async response\n");
print(response);
});
future.wait();
Пожалуйста, смотрите GitHub вопрос для окончательного результата.
Других решений пока нет …