Отправка HTTP через сокеты: 400 Bad request
import socket
import re
mysock= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
url=input ("Enter a url: ")
try:
re.search("^http[s]?://.*?", url)
except:
print ("Error")
prot, hostdoc= url.split("//")
host, doc= hostdoc.split ("/")
mysock.connect((host, 80))
cmd = 'GET url HTTP/1.0\r\n\r\n'.encode()
mysock.send (cmd)
while True:
data=mysock.recv(512)
if len(data)<1:
break
print (data.decode(), end='')
mysock.close()
Выдаёт ошибку в Питоне 3.7 (400 Bad request). Ссылки рабочие.
Для решения задачи можно пользоваться только socket. В чём ошибка?
Ответы (1 шт):
Автор решения: gil9red
→ Ссылка
Нужно добавлять /, например: GET / HTTP/1.0\r\n\r\n (это запрос index), если у вас url будет http://google.ru/search, тогда GET /search HTTP/1.0\r\n\r\n.
Советую парсить url соответствующими инструментами, например urlsplit.
Попробуйте так:
from urllib.parse import urlsplit
import socket
import re
mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
url = input("Enter a url: ")
try:
re.search("^http[s]?://.*?", url)
except:
print("Error")
result = urlsplit(url)
mysock.connect((result.netloc, 80))
cmd = f'GET {result.path} HTTP/1.0\r\n\r\n'.encode()
mysock.send(cmd)
while True:
data=mysock.recv(512)
if len(data)<1:
break
print(data.decode(), end='')
mysock.close()
При url = "http://google.ru", успешно вернуло данные:
HTTP/1.0 200 OK\r\nDate: Wed, 25 Mar 2020 19:09:42 GMT\r\nExpires: -1\r\nCache-Control: private ...
Пример работы по шагам:
url = 'http://google.ru/'
result = urlsplit(url)
# SplitResult(scheme='http', netloc='google.ru', path='/', query='', fragment='')
mysock.connect((result.netloc, 80))
# google.ru : 80
cmd = f'GET {result.path} HTTP/1.0\r\n\r\n'.encode()
# b'GET / HTTP/1.0\r\n\r\n'
Еще пример:
url = 'http://google.ru/search'
result = urlsplit(url)
# SplitResult(scheme='http', netloc='google.ru', path='/search', query='', fragment='')
...
cmd = f'GET {result.path} HTTP/1.0\r\n\r\n'.encode()
# b'GET /search HTTP/1.0\r\n\r\n'
UPD.
Для работы сокетов по HTTPS нужен 443 порт, использовать ssl.
from urllib.parse import urlsplit
import socket
import ssl
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
url = 'https://www.coursera.org/robots.txt'
result = urlsplit(url)
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
s_sock = context.wrap_socket(socket, server_hostname=result.netloc)
s_sock.connect((result.netloc, 443))
cmd = f'GET {result.path} HTTP/1.1\r\nHost: {result.netloc}\r\n\r\n'.encode()
s_sock.send(cmd)
while True:
data = s_sock.recv(512)
if not data:
break
print(data.decode(), end='')
s_sock.close()