LINUX.ORG.RU

HEAD запрос не работает. BAD REQUEST


0

0

Очередной кусок кода, который не работает так, как нужно. Если у кого-то будет время - посмотрите пожалуйста. Буду благодарен за любые советы. Вот собственно код:

int LoadHttp(char * server,char * url)
{
	int sock, port;//наш сокет, по которому мы будем общатся с сервером
	struct sockaddr_in serv_addr;//структура, для установки соединения
	struct hostent * serverAddres;//структура, для получения фактического IP адреса сервера
	char *strGet = "HEAD ";//стандартные строки в HTTP запросе
	char *strHTTP1 = "\n\rHTTP/1.1";//стандартные строки в HTTP запросе
	char *strAccept = "\n\rAccept: text/html";
	char *strHost = "\n\rHost: ";//стандартные строки в HTTP запросе
	char *strEnd = "\n\r\n\r";//стандартные строки в HTTP запросе
	int sendStrLen = strlen(strGet)+strlen(url)+strlen(strHTTP1) +strlen(strHost)+strlen(strAccept)+strlen(server)+strlen(strEnd);//считаем длинну строки-запроса
	char * sendStr = new char [sendStrLen];//создаем строку соответствующей длинны, в которой будет хранится текст запроса

	char *tmpStrPointer;//переменная-указатель. С помощью нее мы заполним нашу строку-запрос необходимой информацией.

	tmpStrPointer = sendStr;//устанавливаем указатель на начало строки
	strcpy(tmpStrPointer,strGet);//копируем строку GET в нашу строку.
	tmpStrPointer += strlen(strGet);//отступаем от начала строки на необходимое кол=во символов
	strcpy(tmpStrPointer,url);//добавляем в нашу строку путь к необходимой нам странице
	tmpStrPointer += strlen(url);//отступаем на необходимое кол-во символов	вправо

	strcpy(tmpStrPointer,strHTTP1);//добавляем в нашу строку заголовок с версией протокола
	tmpStrPointer += strlen(strHTTP1);//отступаем на необходимое кол-во символов	вправо

	strcpy(tmpStrPointer,strHost);//добавляем в нашу строку заголовок Host
	tmpStrPointer += strlen(strHost);//отступаем на необходимое кол-во символов	вправо	
	strcpy(tmpStrPointer,server);//дополняем заголовок Host именем сервера
	tmpStrPointer += strlen(server);//отступаем на необходимое кол-во символов	вправо

	strcpy(tmpStrPointer,strAccept);//добавляем в нашу строку заголовок Accept
	tmpStrPointer += strlen(strAccept);//отступаем на необходимое кол-во символов	вправо

	strcpy(tmpStrPointer,strEnd);//добавляем в строку завершающие символы

	write(1,sendStr,sendStrLen);
	sock = socket(AF_INET, SOCK_STREAM, 0);//создаем сокет
	if (sock < 0)//если сокет не создан - сообщаем об ошибке
	{
		printf("socket() failed: %d", errno);
		return EXIT_FAILURE;
	}	


	serverAddres = gethostbyname(server);//получаем адрес сервера по его имени
	if (serverAddres == NULL) //если не удалось получить адрес - сообщаем об ошибке
	{
		printf("Host not found\n");
		return EXIT_FAILURE;
	}


	memset((char *) &serv_addr, 0, sizeof(serv_addr));//заполняем нулями структуру ser_addr
	serv_addr.sin_family = AF_INET;//указываем тип необходимого соединения - соединение интернет
	memcpy(&serv_addr.sin_addr.s_addr, serverAddres->h_addr, serverAddres->h_length);//копируем в нашу структуру для создания соединения реальный IP адрес сервера
	serv_addr.sin_port = htons(80);//указываем порт, через который будем соединятся с сервером
	if (connect(sock,(const sockaddr*) &serv_addr, sizeof(serv_addr)) < 0) //пытаемся соединится. если соединится с сервером не удалось - выводим сообщение об ошибке
	{
		printf("connect() failed: %d", errno);
		return EXIT_FAILURE;
	}


	send(sock, sendStr, sendStrLen,0);//посылаем нашу строку-запрос на сервер
	

	char *bufR = new char [MaxPageLength];//объявляем буфер для получения информации с сервера
	memset(bufR, 0, 100);//очищаем буфер
	int readed = recv(sock, bufR, MaxPageLength-1,0);//получаем новое сообщение и записываем кол-во принятых байт в переменную readae
	while(readed!=0)//до тех пор, пока кол-во прочитанных байт не равно 0
	{
		write(outID,bufR,readed);
		readed = recv(sock, bufR, MaxPageLength-1,0);//читаем следующую порцию данных
	}
	printf("\n");
	close(sock);//закрываем наш сокет = закрываем соединение с сервером
	return 0;//завершаем процедуру. ошибок не возникло
}
Сервер почему-то возвращает:
<html>
<head><title>400 Bad Request</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<hr><center>nginx/0.6.31</center>
</body>
</html>
Может я где-то в запросе что-то не то поставил, но вроде перерыл вдоль и поперек стандарт HTTP и там все должно быть именно так.

P.S. Может я чего-то путаю, но ведь сервер перед текстом странички должне вернуть HTTP заголовки. А тут ими и не пахло...

★★★★★

>    char *strHTTP1 = "\n\rHTTP/1.1";//стандартные строки в HTTP запросе

Версия HTTP олжна быть в первой строке, а не на отдельной. Т.е. запрос должен быть вроде

GET /index.html HTTP/1.1
Host: www.example.org
_                          (тут пустая строка =))

а у тебя получается нечто вроде

GET /index.html
HTTP/1.1
Host: www.example.org
_

и сервер это не может понять. Для уверенности выведи sendStr на терминал, после того как соберёшь запрос, и посмотри как он выглядит.

Deleted
()

> P.S. Может я чего-то путаю, но ведь сервер перед текстом странички должне вернуть HTTP заголовки. А тут ими и не пахло...

А это уже видимо кривость конкретного сервера.

Deleted
()
Ответ на: комментарий от Deleted

> > P.S. Может я чего-то путаю, но ведь сервер перед текстом странички должне вернуть HTTP заголовки. А тут ими и не пахло...

> А это уже видимо кривость конкретного сервера.

Нет. Просто если версия HTTP не указана (посмотри сам свой вышестоящий ответ), то сервер предполагает HTTP/0.99 и в соответствии с ним имеет право отдать тело документа без заголовков :-)

А вообще код УЖАСЕН! Почему бы было не задействовать тот же sprintf чтобы заполнить буфер и не прибегать к этому потоку бреда???

no-dashi ★★★★★
()

Это уже третий твой топик. Перечитай предыдущие два, там всё было рассказано. Например, про то что тебе помог бы снифер.

true_admin ★★★★★
()

$ echo -e "HEAD / HTTP/1.1\r\nHost: ya.ru\r\nAccept: text/html\r\n\r\n" | nc ya.ru 80
HTTP/1.1 200 OK

$ echo -e "HEAD / HTTP/1.1\n\rHost: ya.ru\n\rAccept: text/html\n\r\n\r" | nc ya.ru 80
HTTP/1.0 400 Bad Request

summatus
()

Да сделай ты уже popen("wget") и успокойся

Absurd ★★★
()
Ответ на: комментарий от summatus

Большое спасибо summatus. Теперь наконец-то понял, в чем у меня постоянно проблемы. Действительно перепутал \n и \r местами. Даже внимания на это не обращал.
Господам, советующим использовать снифер: разглядеть эту ошибку так и не мог, т.к. на экран у меня выводился непременно:
GET /
HTTP/1.1
Host:lenta.ru

и все работало, а вот когда выводилось:
GET / HTTP/1.1
Host: lenta.ru
почему-то ничего не работало и я не мог понять, почему вроде бы верный с виду запрос постоянно нарывается на 404.

Еще раз спасибо summator.
Если есть желание - скинь мне свой номер кошелька в личку - закину 1 WMZ.
Ты мне действительно очень помог!!!

trex6 ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.