Python сокет http библиотека почтовый запрос не работает при передаче данных - PullRequest
0 голосов
/ 01 октября 2018

Итак, как сказал мой заголовок, я создаю небольшую http-библиотеку с базовыми запросами get и post.Я получил запрос на получение, но мой почтовый запрос ведет себя странно.Каждый раз, когда я передаю данные на почту, они не получают ответ.Кажется, все работает нормально, когда я не передаю атрибут body (последний).Я не пытаюсь использовать библиотеку запросов, я пытаюсь создать ее самостоятельно.

Может кто-нибудь увидеть, что я делаю неправильно?Я чувствую, что мне не хватает заголовка, но я не знаю, какой.

import socket
from urllib.parse import urlparse
import json

TCRLF = "\r\n\r\n"
CRLF = "\r\n"



def post(url, headers=None, data=""):

    connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    request = build_request("POST", url, headers, data)
    print("request: " + request)
    print("url:" + url)
    print("headers :" + str(headers))

    url = urlparse(url)

    connection.connect((url.hostname, url.port or 80))
    connection.sendall(request.encode("UTF-8"))
    response = connection.recv(4096).decode("UTF-8")
    print("response: " +  response)
    #
    # (response_header, response_body) = response.split(TCRLF)
    # response_body = json.loads(response_body)
    #
    # print(response_header)
    # print(response_body)

    return None

def build_request(req_type, url, headers=None, body=""):

    url = urlparse(url)

    hostname = url.hostname
    path = url.path or "/"
    query = url.query
    port = url.port or 80

    print("hostname" + hostname)
    print("path : " + path)
    print("query :" + query)
    print("port :" + str(port))
    print("body:" + str(body))

    uri = "{}?{}".format(path, query) if query else path

    formatted_headers = "".join(
        "{}:{}\r\n".format(k, v) for k, v in headers.items())


    print("formatted: "+ formatted_headers)

    requestGet = "GET " + uri + " HTTP/1.0" + CRLF + "Host:" + hostname + CRLF + formatted_headers + TCRLF

    ##TODO body failing when passing object
    requestPost = "POST " + uri + " HTTP/1.0" + CRLF + "Host: " + hostname + CRLF + "Content-Length: " + str(
        len(body)) + CRLF + formatted_headers + TCRLF + body + TCRLF

    print("Request" + requestPost)

    if req_type=="POST":
        return requestPost
    else:
        return requestGet


def main():
    post("http://httpbin.org/post", {"Content-Type": "application/json" }, "{'Assignment': 1}")

if __name__ == '__main__':
    main()

1 Ответ

0 голосов
/ 01 октября 2018

Понятия не имею, откуда у вас знания HTTP.Но ни ваш GET, ни ваш запрос POST не являются правильными запросами в соответствии со стандартом HTTP.Для GET вы добавляете дополнительный \r\n в конце (т.е. GET / HTTP/1.0\r\nHost: example.com\r\n\r\n\r\n - последний \r\n слишком много), а для POST вы делаете то же самое, а также добавляете некоторые недействительные данные (TCRLF) после тела запроса,

Это дополнительное \r\n, которое вы добавляете после того, как заголовок запроса засчитывается в заданный вами Content-length, что означает, что тело HTTP, прочитанное сервером, на два байта короче, чем тело, которое вы намеревались.Вместе с TRCLF, который вы отправляете после тела, фактическое тело HTTP, которое вы отправляете, на 6 байт длиннее значения, которое вы задаете в заголовке Content-Length.

Пожалуйста, обратитесь к стандарту HTTP, чтобы узнать, как должен выглядеть HTTP.нравится - вот для чего нужны стандарты.Не пытайтесь правильно понять, как работает HTTP, просто взглянув на примеры трафика или кода, которые вы найдете в Интернете.В частности, простые примеры кода часто бывают неправильными или неполными и могут работать с некоторыми серверами или в некоторых случаях использования, но не в целом.

Каждый раз, когда я передаю данные на почту, они не получают ответ.

Я не могу воспроизвести утверждение, что ответ вообще не возвращается.Принимая ваш неизмененный код, я фактически получаю ответ от сервера, который включает, среди прочего, представление серверов вашего тела ответа:

...    
"data": "\r\n{'Assignment': ", 
...

Это ваше предполагаемое тело с префиксом неправильного \r\n и сокращенным на двабайт для соответствия заявленным Content-length.При изменении вашего кода для выполнения правильных запросов без неправильных \r\n в разных местах я получаю ожидаемое:

...
"data": "{'Assignment': 1}", 
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...