Разбор исключения из простого запроса POST - PullRequest
0 голосов
/ 17 сентября 2018

Я использую сокеты в C ++ для связи с Elasticsearch. Я могу общаться с моим экземпляром ELK (он работает в docker compose, файлы docker * здесь ).

Вот запрос, который я отправляю:

POST /twitter/_doc/1? HTTP/1.1
Content-Type: application/json; charset=UTF-8
Host: 127.0.0.1:9200
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36
'{ "post_date" : "2017-11-16T14:12:12", "message" : "trying out Elasticsearch FROM CPPPPP" }'
Connection: close

А вот ответ, который я получаю с сервера:

HTTP/1.1 400 Bad Request
content-type: application/json; charset=UTF-8
content-length: 163

{"error":{"root_cause":[{"type":"parse_exception","reason":"request body is required"}],"type":"parse_exception","reason":"request body is required"},"status":400}

Я могу подтвердить, что отправляю и получаю эти данные путем подсчета байтов, отправляемых и получаемых.

Я в замешательстве, потому что, когда я помещаю этот запрос в консоль Kibana, он работает нормально.

Любые идеи о том, что было бы неправильно с отправляемым мной запросом?

Вот код C ++, где я создаю запрос:

std::string post_http = "";
post_http += "POST /twitter/_doc/1? HTTP/1.1\n";
post_http += "Content-Type: application/json; charset=UTF-8\n";
post_http += "Host: ";
post_http += aURL;
post_http += ":9200\n";
post_http += "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36\n";
post_http += "'{ \"post_date\" : \"2017-11-16T14:12:12\", ";
post_http += "\"message\" : \"trying out Elasticsearch FROM CPPPPP\" }'";
post_http += "\r\nConnection: close\r\n\r\n";

Насколько я могу судить, будет проблема с тем, как я создаю запрос в приведенном выше коде.

Ответы [ 2 ]

0 голосов
/ 26 сентября 2018

Проблема возникла из-за отсутствия Content-Body в заголовке, а также из-за того, как долго сокет ожидал ответа.Кажется, что вопреки документации WinSock , вам не следует вызывать метод shutdown, если вы ожидаете ответа от сервера.

Вот что у меня получилось для моего законченного метода:

assert(strcmp(aMethod, "GET") || strcmp(aMethod, "POST") || strcmp(aMethod, "PUT"));

// TODO: Investigate if I actually need to reconnect the socket every time a request is made? 
ConnectSocket();

char Request[MAX_REQUEST_LEN];
strcpy_s(Request, MAX_REQUEST_LEN, aMethod);

strcat_s(Request, MAX_REQUEST_LEN, " ");
strcat_s(Request, MAX_REQUEST_LEN, aIndexParam);
strcat_s(Request, MAX_REQUEST_LEN, RequestHeader);

strcat_s(Request, MAX_REQUEST_LEN, "Content-Length: ");
strcat_s(Request, MAX_REQUEST_LEN, std::to_string(strlen(aMsg)).c_str());
strcat_s(Request, MAX_REQUEST_LEN, "\r\n");

strcat_s(Request, MAX_REQUEST_LEN, ConnectionClose);
strcat_s(Request, MAX_REQUEST_LEN, aMsg);
strcat_s(Request, MAX_REQUEST_LEN, "\r\n");

Как видите, я перешел к использованию char * вместо std::String, что дало мнеповышение производительности на 30%.Кроме того, теперь в заголовке есть тег Content-Length.

Вот так выглядят мои последние заголовки:

POST /twitter/_doc/ HTTP/1.1
Content-Type: application/json; charset=UTF-8
Content-Encoding: identity
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36
Host:  HTTP/1.1
127.0.0.1:9200
Content-Length: 112
Connection: close

{ "user" : "kimchy", "post_date" : "2018-09-16T14:12:12", "message" : "trying out Elasticsearch FROM c++ BOII" }
0 голосов
/ 17 сентября 2018

Судя по вашему коду, вы видите, что вы смешали тело внутри заголовков.Таким образом, у вас фактически нет тела в вашем HTTP-сообщении.

Пожалуйста, посмотрите https://en.wikipedia.org/wiki/HTTP_message_body для описания того, как составляется HTTP-сообщение, особенно обратите внимание на необходимость наличия ПУСТОЙ строки между заголовками иbody.

В вашем случае решение может состоять в том, чтобы изменить вашу строку post_http на:

std::string post_http = "";
post_http += "POST /twitter/_doc/1? HTTP/1.1\r\n";
post_http += "Content-Type: application/json; charset=UTF-8\r\n";
post_http += "Host: " + aURL + ":9200\r\n";
post_http += "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36\r\n";
post_http += "Connection: close\r\n"
post_http += "\r\n"; // EMPTY line between header and body.
post_http += "'{ \"post_date\" : \"2017-11-16T14:12:12\", ";
post_http += "\"message\" : \"trying out Elasticsearch FROM CPPPPP\" }'";

Я также изменил окончания строк, чтобы все были последовательными "\ r \ n",как указано в связанной статье.

Может также помочь определить строку const, чтобы дать имя последовательности окончания строки, например:

const char* HTTP_LINE_END = "\r\n";
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...