Мне нужно создать http-сервер без использования HTTP-библиотеки.
У меня запущен сервер и загружена html-страница, но мои теги <img src = "..."/> не загружаются, я получаю звонок, но не могу предварительно установить png / JPEG на странице.
# Define socket host and port
SERVER_HOST = '0.0.0.0'
SERVER_PORT = 8000
# Create socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((SERVER_HOST, SERVER_PORT))
server_socket.listen(1)
print('Listening on port %s ...' % SERVER_PORT)
while True:
# Wait for client connections
client_connection, client_address = server_socket.accept()
# Handle client request
request = client_connection.recv(1024).decode()
content = handle_request(request)
# Send HTTP response
if content:
response = 'HTTP/1.1 200 OK\n\n'
response += content
else:
response = 'HTTP/1.1 404 NOT FOUND\n\nFile Not Found'
client_connection.sendall(response.encode())
client_connection.close()
# Close socket
server_socket.close()
def handle_request(request):
http = HttpHandler.HTTPHandler
# Parse headers
print(request)
headers = request.split('\n')
get_content = headers[0].split()
accept = headers[6].split()
type_content = accept[1].split('/')
try:
# Filename
filename = get_content[1]
if get_content[0] == "GET":
content = http.get(None, get_content[1], type_content[0])
return content
except FileNotFoundError:
return None
class HTTPHandler:
def get(self, args, type):
if args == '/':
args = '/index.html'
fin = open('htdocs' + args)
if type != "image":
fin = open('htdocs/' + args)
if type == "image":
fin = open('htdocs/' + args, 'rb')
# Read file contents
content = fin.read()
fin.close()
return content
Поймите, что я пытаюсь сделать HTTP 1.1, если вы видите что-то нестандартное, смело можете заранее сказать спасибо.
Возможно, я ослеп, но я не вижу, куда этот код отправляет строки заголовка в браузер.
@ PM2Ring да, я делаю это в качестве обучающего упражнения, и ссылку, которую вы отправляете, я могу вернуть строку, без проблем с этим кодом, когда страница загружается, если у меня есть тег <img>, браузер делает еще один вызов для ресурса, вот где возникает проблема, я не знаю, как отправить изображение
В ответ на запрос браузера вам необходимо отправить правильные заголовки, а также данные двоичного изображения. Этот ответ показывает, как выглядят заголовки.






Я не знаю, где вы узнали, как работает HTTP, но я почти уверен, что вы не изучали фактический стандарт, что вам следует делать при реализации протокола. Некоторые примечания о вашей реализации:
\r\n, а не \n. Это верно как для ответов сервера, так и для запросов от клиента.recv. Но запросы могут иметь произвольную длину, и нет гарантии, что вы получите все в рамках одного recv (TCP - это протокол потоковой передачи, а не протокол сообщений).Content-length или использовать кодирование передачи по частям.Content-Type, то есть Content-type: text/html для HTML и Content-type: image/jpeg для изображений JPEG. Без этого браузер мог бы правильно или ошибочно предположить, что это за тип, или, в зависимости от контекста, также мог бы настаивать на правильном заголовке типа содержимого.Кроме того, если вы устраняете такие проблемы, полезно выяснить, чем фактически происходит обмен между клиентом и сервером. Возможно, вы проверили это сами, но не включили такую информацию в свой вопрос. Ваше единственное описание ошибки - «... Я получил звонок, но не могу предварительно установить png / JPEG на странице», а затем дамп вашего кода.
Спасибо за помощь со стандартом, проблема заключалась в том, что я отправлял байты в виде строки (в конкатенации), а не в виде байтов.
Закончилось так:
while True:
# Wait for client connections
client_connection, client_address = server_socket.accept()
# Handle client request
request = client_connection.recv(10240).decode()
content = handle_request(request)
# Send HTTP response
if content:
if str(content).find("html") > 0:
client_connection.send('HTTP/1.1 200 OK\n\n'.encode())
client_connection.send(content.encode())
else:
client_connection.send('HTTP/1.1 200 OK\r\n'.encode())
client_connection.send("Content-Type: image/jpeg\r\n".encode())
client_connection.send("Accept-Ranges: bytes\r\n\r\n".encode())
client_connection.send(content)
else:
response = 'HTTP/1.1 404 NOT FOUND\r\nFile Not Found'
client_connection.close()
И метод Get, например:
class HTTPHandler:
def get(self, args, type):
if args == '/':
args = '/index.html'
fin = open('htdocs' + args)
if type != "image":
fin = open('htdocs/' + args)
if type.find("html") == -1:
image_data = open('htdocs/' + args, 'rb')
bytes = image_data.read()
# Content-Type: image/jpeg, image/png \n\n
content = bytes
fin.close()
return content
# Read file contents
content = fin.read()
fin.close()
return content
IPS - CD что-то говорит? Спасибо из будущего!
Почему вы не можете использовать
http.server. Вы делаете это в качестве обучающего упражнения? Если это так, возможно, вы могли бы почерпнуть несколько идей, просмотрев исходный код модуляhttp.serverили Python 2BaseHTTPServer.