POST-запрос с использованием сокетов, не работающих в python

#python

#python

Вопрос:

У меня есть следующий код python:

 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
client.connect(("example.com", 443))
client.send(b'POST /api HTTPS/1.1rnHost: example.comrnUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0rnAccept-Encoding: gzip, deflaternAccept: application/jsonrnConnection: keep-alivernContent-Type: application/jsonrnAuthoriation: aarnContent-Length: 22rnrn')
client.send(b'{"jsonPostData": "aaa"}')
response = client.recv(4096)
response = repr(response)
 

Но он возвращает ошибку 400 bad request без содержимого, я пробовал одни и те же заголовки и json с запросами и aiohttp, и в обоих случаях это работает, есть идеи о том, что я делаю неправильно?

Комментарии:

1. Обычно, используя pypi.org/project/requests это гораздо проще. Вы решили использовать socket его специально? Если нет: w3schools.com/python/ref_requests_post.asp

2. Я использую его специально, так как это быстрее или с несколькими запросами

3. используете ли вы пулы / сеансы соединений с aiohttp / запросами?

4. Почему вы говорите, что это быстрее для нескольких запросов? Вы пытаетесь отправлять запросы на очень удаленный сервер? Например, запрашивать сервер США из Азии? Если это так, у меня есть некоторый опыт использования запросов в этом контексте. Как уже упоминалось, пулы и сеансы очень полезны. Есть несколько других советов

Ответ №1:

Никогда не пишите свой собственный http-клиент, если вы не являетесь экспертом по TCP, TLS, HTTP (S) и API-дизайну, это не будет ни надежным, ни удобным.

Что касается вашего фрагмента кода — вы не можете использовать простые сокеты для безопасных подключений, вы должны использовать безопасные сокеты.

 import socket
import ssl

def request(sock):
    sock.sendall(
        b'POST /post HTTP/1.1rn'
        b'host: postman-echo.comrn'
        b'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0rn'
        # b'Accept-Encoding: gzip, deflatern'  # do you really want to handle it?
        b'accept: application/jsonrn'
        b'connection: keep-alivern'
        b'content-type: application/jsonrn'
        b'content-length: 14rn'
        b'rn'
        b'{"qwe": "rty"}'
    )
    return sock.recv(4096)


if __name__ == "__main__":
    tls = True  # toggle 
    context = ssl.create_default_context()

    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
        if not tls:
            sock.connect(("postman-echo.com", 80))
            response = request(sock)
        else:
            with context.wrap_socket(sock, server_hostname="postman-echo.com") as ssock:
                ssock.connect(("postman-echo.com", 443))
                response = request(ssock)
    print(response)

 

Из ответа

 "json": {"qwe":"rty"}
 

Комментарии:

1. Спасибо за ответ, но я все равно получаю тот же плохой ответ на запрос.

2. Код из ответа работает как есть? Если вы ничего не измените.

3. Да, моя ошибка, неправильно обработал текст сообщения

Ответ №2:

Вы пытаетесь подключиться к SSL-порту, используя не SSL-соединение.

Попробуйте использовать библиотеку запросов. Попробуйте подключиться к порту 80.

Комментарии:

1. Он автоматически переключается на HTTPS, я отредактирую комментарий, но это не проблема.

2. что автоматически переключается на HTTPS? socket модуль очень низкоуровневый, в нем нет ничего автоматического

3. Веб-сервер перенаправляет меня на https