Номер порта не отображается в headers.host - PullRequest
0 голосов
/ 28 мая 2020

Я делаю HTTP-запрос из внешнего интерфейса и вижу номер порта в поле Host заголовка запроса в инструментах разработки (например, xyz.com:1234). Но при использовании модуля запросов python хост показывает только xyz.com. Как я могу узнать номер порта?

1 Ответ

1 голос
/ 28 мая 2020

Библиотеке requests не нужно создавать и добавлять заголовок Host, когда вы используете ее для выполнения запроса, но вы можете добавить заголовок Host, если хотите: просто укажите headers аргумент ключевого слова - например, headers={'Host': 'xyz.com:1234'}, если вы используете ваш пример выше.

Анализ номера порта из URL-адреса, ручной подход

Ваш вопрос, похоже, больше связан с синтаксическим анализом номер порта для запроса, однако пример должен прояснить ситуацию для вас:

from urllib.parse import urlparse
import requests

def get_port(url: str) -> int:
    schema_ports = {'http': 80, 'https': 443}
    parsed_url = urlparse(url)
    if parsed_url.port:
        return parsed_url.port
    return schema_ports.get(parsed_url.scheme, None)

ports = (
    get_port(requests.get('http://localhost:8001').request.url),
    get_port(requests.get('http://google.com').request.url),
    get_port(requests.get('https://google.com').request.url)
)

print(ports) # (8001, 80, 443)

В этом примере есть три HTTP-запроса GET с библиотекой requests. Хотя в этом надуманном примере вы уже видите URL-адрес запроса, если вы работаете над решением на основе объекта generi c requests.models.Response, вы можете получить URL-адрес запроса из атрибута request.url. Затем вам нужно понять, что в случаях, когда порт не указан явно, вам нужно будет вывести разумное значение по умолчанию (поскольку нет явного port). Приведенное выше определение get_port дает пример этого для двух распространенных схем (HTTP и HTTPS).

Дополнительную информацию см. В модуле urllib.parse стандартной библиотеки Python.

Более автоматизированный подход, опирающийся на стандартную библиотеку

Ручной подход, описанный выше, описывает, как думать об этой проблеме в общем c смысле, но он нелегко масштабируется до много общих схем, которые могут существовать (ssh, gopher, et c.).

В системах POSIX файл /etc/services поддерживает сопоставления общих схем обслуживания с портами / протоколами и дополнительными описаниями , например,

http             80/udp     www www-http # World Wide Web HTTP
http             80/tcp     www www-http # World Wide Web HTTP

Функция getservbyname в Python библиотеке socket имеет способ задействовать этот тип сопоставления:

>>> socket.getservbyname('https')
443
>>> socket.getservbyname('http')
80

Этим мы можем улучшить мой первый пример, чтобы не указывать сопоставления для общих схем вручную:

import socket
from urllib.parse import urlparse
import requests

def get_port(url: str) -> int:
    parsed_url = urlparse(url)
    if parsed_url.port:
        return parsed_url.port
    try:
        return socket.getservbyname(parsed_url.scheme)
    except OSError:
        return None

ports = (
    get_port(requests.get('http://localhost:8001').request.url),
    get_port(requests.get('http://google.com').request.url),
    get_port(requests.get('https://google.com').request.url)
)

print(ports) # (8001, 80, 443)
...