HTTP server and HTTP client using Socket (+ web browser) --Python3

Untitled.jpg

HTTP communication using Socket module

A simple example of HTTP communication using the python3 socket module

To put it simply, HTTP is a rule (data is called TCP payload) for the part of TCP data (called TCP payload) that can be any data because HTML files are sent by TCP communication (not necessarily TCP). (Please follow this format), so you can send the data according to that format with recv, send.

Here, proceed while reading RFC7230, RFC7230 Japanese translation.

TCPandHTTP.jpg

http通信.jpg

Start-line and header-section

About the start line start-line

An HTTP message can be either a client-to-server request or a server-to-client response. The two can be distinguished from each other at this start line. The starting line is the request line in the former case and the [status line](https://help.amanohina. It takes the format com / RFC7230-ja.html#p.status-line).

About header section header-section

This time we will use the following header fields.

Server side

  1. Server
  2. Connection
  3. Content-Type
  4. Content-Length

Client side

  1. Accept
  2. Host
  3. Connection
  4. User-Agent

In fact, I didn't use any header field values this time.

Implementation so far

The values in the code and header clauses are fixed here, but as you know, they are determined dynamically.

Client side request line + header clause

RETURN_PHRASE = '\r\n'
VERSION = 'HTTP/1.1'


def make_request_line(mtd, request_target):
    '''Return http_request-line'''

    request_line = \
        mtd + ' ' + request_target + ' ' + VERSION + RETURN_PHRASE
    return request_line


def make_header_section():
    '''Return http_header-section'''

    field_values = {
        'Host': '192.168.1.200',
        'Accept': 'html/plain',
        'Connection': 'close',
        'User-Agent': 'Suzukaze Browser 1.0'
    }
    header_sc = 'Host:' + field_values['Host'] + RETURN_PHRASE
    header_sc += 'Accept:' + field_values['Accept'] + RETURN_PHRASE
    header_sc += 'Connection:' + field_values['Connection'] + RETURN_PHRASE
    header_sc += 'User-Agent:' + field_values['User-Agent'] + RETURN_PHRASE
    header_sc += RETURN_PHRASE
    return header_sc


mtd = 'GET'
request_target = '/'
request_line = make_request_line(mtd, request_target)

header_section = make_header_section()

print(header_section)

The function make_request_line (method, request target)-> request line returns:

GET / HTTP/1.1

The function make_header_section ()-> header section returns:

Host:192.168.1.200
Accept:html/plain
Connection:close
User-Agent:Suzukaze Browser 1.0
Blank line

Server-side status line + header clause

The code is fixed at 200. So reason_phrases is superfluous but added for the mood.

RETURN_PHRASE = '\r\n'
VERSION = 'HTTP/1.1'


def make_status_line():
    '''Return http_staus_line'''

    reason_phrases = {
        '200': 'OK',
        '403': 'Forbidden',
        '404': 'Not Found',
        '405': 'Method Not Allowed'
    }
    status_line = \
        VERSION + ' ' + '200' + ' ' + reason_phrases['200'] + RETURN_PHRASE
    return status_line


def make_header_section(content_length):
    '''Return http_header_section'''

    field_values = {
        'Server': 'Suzukaze Server 1.0',
        'Date': datetime.now(timezone.utc).strftime(r'%a, %d %b %Y %X %Z'),
        'Connection': 'close',
        'Content-Type': 'html/plain',
        'Content-Length': content_length
    }
    header_sc = 'Date:' + field_values['Date'] + RETURN_PHRASE
    header_sc += 'Server:' + field_values['Server'] + RETURN_PHRASE
    header_sc += 'Connection' + field_values['Connection'] + RETURN_PHRASE
    header_sc += 'Content-Type' + field_values['Content-Type'] + RETURN_PHRASE
    header_sc += 'Content-Length' + field_values['Cotent-Length'] + RETURN_PHRASE
    header_sc += RETURN_PHRASE
    return header_sc


def read_index_html():
    '''Return index.html and that length'''

    with open('index.html', 'rb') as f:
        index_html = f.read()
        index_len = len(index_html)
        return index_html, index_len


status_line = make_status_line()

index_html, index_len = read_index_html()
content_length = index_len

header_section = make_header_section(content_length)
The function make_status_line ()-> status line returns:
HTTP/1.1 200 OK
The function make_header_section (Content-Length value)-> header section returns:
Date:Mon, 00 Nov 2020 00:00:00 UTC
Server:Suzukaze Server 1.0
Connection:close
Content-Type:html/plain
Content-Length:1224
Blank line
The function read_index_html ()-> the contents of index.html, the length of index.html returns:
b"<!DOCTYPE html>\n<head>\n    <meta charset='utf-8'>\n</head>\n<style>\n* 
(Abbreviation)
ab\xe3\x81\xa4\xe3\x81\x84\xe3\x81\xa6</li>\n                <li>\xe5\x95\x8f\xe3\x81\x84\xe5\x90\x88\xe3\x82\x8f\xe3\x81\x9b</li>\n            </ul>\n        </footer>\n    </div>\n</body>\n"
1224

Information that the server needs to retrieve from the request

In this code, we know that the request is a'/', so we don't need a request-target, and we also close the Connection, so we don't have the information that the server needs after all. So the request line and header clause are passed through.

Message-body

Even if we say that we implement the message body on the server side, we have already read index.html as a byte string, so we just attach it to the end of the header clause on the server side. There is no message body on the client side.

It should be noted here that the start line and header clause are Unicode character strings (str type). Since it is necessary to make it a byte-like-object to send it with a socket, convert it.

Client side

mtd = 'GET'
request_target = '/'
request_line = make_request_line(mtd, request_target)

header_section = make_header_section()

http_msg = \
    bytes(request_line, 'utf-8') + bytes(request_line, 'utf-8')

Server side

status_line = make_status_line()

index_html, index_len = read_index_html()
msg_body = index_html
content_length = str(index_len)

header_section = make_header_section(content_length)

http_msg = \
    bytes(status_line, 'utf-8') + bytes(header_section, 'utf-8') + msg_body

Implementation of socket communication

All you have to do now is send this HTTP message to each other.

The code here is based on TCP communication using Socket module-Python3.

Server side

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(SERVER_ADDRESS)
sock.listen(0)

try:
    conn_sock, client_address = sock.accept()
    print_msg('ac', 'The connection accepted.')
    print_msg('i', '{}:{} --------> {}:{}'
              .format(client_address[0], client_address[1],
                      SERVER_ADDRESS[0], SERVER_ADDRESS[1]))

    # Receiving the request
    recd_data = b''
    while True:
        data = conn_sock.recv(32)
        if not data:
            break
        recd_data += data
    print_msg('i', 'Total received: {}'.format(recd_data))

    # Sending the response
    http_msg = make_http_msg()
    remaining = len(http_msg)
    res = 0
    while remaining > 0:
        res = conn_sock.send(http_msg[res:])
        remaining -= res
finally:
    conn_sock.shutdown(socket.SHUT_WR)
    conn_sock.close()
    print_msg('cl', 'The connection closed.')

Client side

You can declare that you will not send any more data to the server side by shutting down after sending the request. (Empty bytes are sent at the socket level, so the server can detect the end of the request by receiving an empty byte.)

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

try:
    sock.connect(SERVER_ADDRESS)
    print_msg('cn', 'The connection accepted')

    # Sending the request
    http_msg = make_http_msg()
    remaining = len(make_http_msg())
    res = 0
    while remaining > 0:
        res = sock.send(http_msg[res:])
        remaining -= res

    sock.shutdown(socket.SHUT_WR)

    # Receiving the response
    recd_data = b''
    while True:
        data = sock.recv(32)
        print(data)
        if not data:
            break
        recd_data += data
finally:
    sock.close()
    print_msg('cl', 'The connection closed.')

Extract data

Client side

For the time being, the client side needs to take out the following two.

  1. Status line information. This is retrieved as a dictionary with the following regular expression.
STS_LINE_PTN = b'''
(?P<version>HTTP/[0-9][.][0-9])[ ]
(?P<status_code>[0-9][0-9][0-9])[ ]
(?P<reason>([!\"#$%&\'()*+,-./0-9:;<=>?@A-Z[\\]^_`a-z{|}~ ]|\t)+)
([\r][\n])
'''

It is taken out as follows.

{'version': b'HTTP/1.1', 'status_code': b'200', 'reason': b'OK'}
  1. A message body containing the html code. Since the end of the header clause is a blank line rule, get the last index of the part that matches b'\ r \ n \ r \ n' and set that index to start of[start: end]. To generate a new (message body only) byte string. Then decode it to get the original html code. That is, it is equal to the following character string (html_source) on the server side.
with open('sample.html', 'r') as f:
	html_source = f.read()

Server side

So far, there is no information required on the server side.

Display the obtained html like a browser

Here we make a simple html viewer using Pyqt5. The UI is created using a designer, converted to Python3 code with PyQt5 UI code generator 5.15.1, and the code is tampered with. Originally, the logic added by the user is written in a class created separately so that there is no problem even if the UI is rewritten, but this time the UI will not be rewritten, so set it as it is. The browser looks like this: Import this module with the main module that performs socket communication.

browser_app.py


import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWebEngineWidgets import QWebEngineView as QWebView


class Ui_dialog(object):
    def setupUi(self, dialog, html_source):
        dialog.setObjectName('dialog')
        dialog.resize(1000, 650)
        self.stackedWidget = QtWidgets.QStackedWidget(dialog)
        self.stackedWidget.setGeometry(QtCore.QRect(10, 50, 980, 590))
        self.stackedWidget.setObjectName('stackedWidget')
        self.page_1 = QtWidgets.QWidget()
        self.page_1.setObjectName('page_1')
        self.webView = QWebView(self.page_1)
        self.webView.setGeometry(QtCore.QRect(0, 0, 980, 590))
        self.webView.setObjectName('webView')
        self.stackedWidget.addWidget(self.page_1)
        self.page_2 = QtWidgets.QWidget()
        self.page_2.setObjectName('page_2')
        self.page_2_title = QtWidgets.QLabel(self.page_2)
        self.page_2_title.setGeometry(QtCore.QRect(370, 60, 240, 50))
        font = QtGui.QFont()
        font.setPointSize(24)
        self.page_2_title.setFont(font)
        self.page_2_title.setObjectName('page_2_title')
        self.page_2_label1 = QtWidgets.QLabel(self.page_2)
        self.page_2_label1.setGeometry(QtCore.QRect(435, 230, 110, 22))
        font = QtGui.QFont()
        font.setPointSize(16)
        self.page_2_label1.setFont(font)
        self.page_2_label1.setObjectName('page_2_label1')
        self.page_2_ip = QtWidgets.QLineEdit(self.page_2)
        self.page_2_ip.setGeometry(QtCore.QRect(435, 262, 110, 28))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.page_2_ip.setFont(font)
        self.page_2_ip.setObjectName('page_2_ip')
        self.page_2_label2 = QtWidgets.QLabel(self.page_2)
        self.page_2_label2.setGeometry(QtCore.QRect(468, 310, 42, 16))
        font = QtGui.QFont()
        font.setPointSize(16)
        self.page_2_label2.setFont(font)
        self.page_2_label2.setObjectName('page_2_label2')
        self.page_2_url = QtWidgets.QLineEdit(self.page_2)
        self.page_2_url.setGeometry(QtCore.QRect(335, 336, 310, 28))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.page_2_url.setFont(font)
        self.page_2_url.setObjectName('page_2_url')
        self.page_2_save = QtWidgets.QPushButton(self.page_2)
        self.page_2_save.setGeometry(QtCore.QRect(425, 384, 130, 40))
        font = QtGui.QFont()
        font.setPointSize(18)
        self.page_2_save.setFont(font)
        self.page_2_save.setObjectName('page_2_save')
        self.stackedWidget.addWidget(self.page_2)
        self.url_lineEdit = QtWidgets.QLineEdit(dialog)
        self.url_lineEdit.setGeometry(QtCore.QRect(10, 10, 666, 30))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.url_lineEdit.setFont(font)
        self.url_lineEdit.setObjectName('url_lineEdit')
        self.search_btn = QtWidgets.QPushButton(dialog)
        self.search_btn.setGeometry(QtCore.QRect(670, 10, 90, 30))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.search_btn.setFont(font)
        self.search_btn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        self.search_btn.setObjectName('search_btn')
        self.config_btn = QtWidgets.QPushButton(dialog)
        self.config_btn.setGeometry(QtCore.QRect(780, 10, 60, 30))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.config_btn.setFont(font)
        self.config_btn.setObjectName('config_btn')

        # ----------------------------------------------

        self.url_lineEdit.setText('in preparation')
        self.page_2_title.setText('Setting the DNS')
        self.page_2_label1.setText('IP Address')
        self.page_2_ip.setText('in preparation')
        self.page_2_label2.setText('URL')
        self.page_2_url.setText('in preparation')

        self.webView.setHtml(html_source)

        # ----------------------------------------------

        QtCore.QMetaObject.connectSlotsByName(dialog)


def mybrowser(html_source):
    app = QtWidgets.QApplication(sys.argv)
    dialog = QtWidgets.QDialog()
    ui = Ui_dialog()
    ui.setupUi(dialog, html_source)
    dialog.show()
    sys.exit(app.exec_())

Put this in the same directory, import it on the client side and call it as follows.

status_dict, res_msg = status_line_parser(recd_data)

if status_dict['status_code'].decode() == '200':
    html_lines = get_msg_body(res_msg)
    html_lines = html_lines.decode()
    mybrowser(html_lines)

Then

Untitled.jpg

It is displayed like this.

Source code

client.py

client.py


import socket
import re
from colored_print import print_msg
from browser_app import mybrowser


# Request


SERVER_ADDRESS = ('192.168.1.201', 8000)
RETURN_PHRASE = '\r\n'
VERSION = 'HTTP/1.1'


def make_request_line(mtd, request_target):
    '''Return http_request-line'''

    request_line = \
        mtd + ' ' + request_target + ' ' + VERSION + RETURN_PHRASE
    return request_line


def make_header_section():
    '''Return http_header-section'''

    field_values = {
        'Host': '192.168.1.200',
        'Accept': 'html/plain',
        'Connection': 'close',
        'User-Agent': 'Suzukaze-Browser-1.0'
    }
    header_sc = 'Host:' + field_values['Host'] + RETURN_PHRASE
    header_sc += 'Accept:' + field_values['Accept'] + RETURN_PHRASE
    header_sc += 'Connection:' + field_values['Connection'] + RETURN_PHRASE
    header_sc += 'User-Agent:' + field_values['User-Agent'] + RETURN_PHRASE
    header_sc += RETURN_PHRASE
    return header_sc


def make_http_msg():
    '''Return http-message'''

    mtd = 'GET'
    request_target = '/'
    request_line = make_request_line(mtd, request_target)

    header_section = make_header_section()

    http_msg = \
        bytes(request_line, 'utf-8') + bytes(header_section, 'utf-8')
    return http_msg


# Response


def status_line_parser(msg_lines):
    '''Return dict of status line and http_msg except status line'''

    STS_LINE_PTN = b'''
    (?P<version>HTTP/[0-9][.][0-9])[ ]
    (?P<status_code>[0-9][0-9][0-9])[ ]
    (?P<reason>([!\"#$%&\'()*+,-./0-9:;<=>?@A-Z[\\]^_`a-z{|}~ ]|\t)+)
    ([\r][\n])
    '''
    p_sts_line = re.compile(STS_LINE_PTN, re.VERBOSE)

    m_sts_line = p_sts_line.match(msg_lines)
    if m_sts_line is not None:
        sts_line_dict = m_sts_line.groupdict()
        return sts_line_dict, msg_lines[m_sts_line.end():]


def get_msg_body(msg_lines):
    '''Return a message body'''
    
    end = msg_lines.rfind(b'\r\n\r\n')
    print(end)
    if end is not -1:
        return msg_lines[end:]
    else:
        raise ValueError('msg_lines is a invalid format')


########################################################################


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

try:
    sock.connect(SERVER_ADDRESS)
    print_msg('cn', 'The connection accepted')

    # Sending the request
    http_msg = make_http_msg()
    remaining = len(make_http_msg())
    res = 0
    while remaining > 0:
        res = sock.send(http_msg[res:])
        remaining -= res

    sock.shutdown(socket.SHUT_WR)

    # Receiving the response
    recd_data = b''
    while True:
        data = sock.recv(32)
        print(data)
        if not data:
            break
        recd_data += data
finally:
    sock.close()
    print_msg('cl', 'The connection closed.')


status_dict, res_msg = status_line_parser(recd_data)

if status_dict['status_code'].decode() == '200':
    html_lines = get_msg_body(res_msg)
    html_lines = html_lines.decode()
    mybrowser(html_lines)

server.py

server.py


import socket
from datetime import datetime, timezone
from colored_print import print_msg


# Response


SERVER_ADDRESS = ('192.168.1.12', 8000)
RETURN_PHRASE = '\r\n'
VERSION = 'HTTP/1.1'


def make_status_line():
    '''Return http_staus-line'''

    reason_phrases = {
        '200': 'OK',
        '403': 'Forbidden',
        '404': 'Not Found',
        '405': 'Method Not Allowed'
    }
    status_line = \
        VERSION + ' ' + '200' + ' ' + reason_phrases['200'] + RETURN_PHRASE
    return status_line


def make_header_section(content_length):
    '''Return http_header-section'''

    field_values = {
        'Server': 'Suzukaze Server 1.0',
        'Date': datetime.now(timezone.utc).strftime(r'%a, %d %b %Y %X %Z'),
        'Connection': 'close',
        'Content-Type': 'html/plain',
        'Content-Length': content_length
    }
    header_sc = 'Date:' + field_values['Date'] + RETURN_PHRASE
    header_sc += 'Server:' + field_values['Server'] + RETURN_PHRASE
    header_sc += 'Connection:' + field_values['Connection'] + RETURN_PHRASE
    header_sc += 'Content-Type:' + field_values['Content-Type'] + RETURN_PHRASE
    header_sc += 'Content-Length:' + field_values['Content-Length'] + RETURN_PHRASE
    header_sc += RETURN_PHRASE
    return header_sc


def read_index_html():
    '''Return index.html and that length'''

    with open('index.html', 'rb') as f:
        index_html = f.read()
        index_len = len(index_html)
        return index_html, index_len


def make_http_msg():
    status_line = make_status_line()

    index_html, index_len = read_index_html()
    msg_body = index_html
    content_length = str(index_len)

    header_section = make_header_section(content_length)

    http_msg = \
        bytes(status_line, 'utf-8') + bytes(header_section, 'utf-8') + msg_body
    return http_msg


###############################################################


sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(SERVER_ADDRESS)
sock.listen(0)

try:
    conn_sock, client_address = sock.accept()
    print_msg('ac', 'The connection accepted.')
    print_msg('i', '{}:{} --------> {}:{}'
              .format(client_address[0], client_address[1],
                      SERVER_ADDRESS[0], SERVER_ADDRESS[1]))

    # Receiving the request
    recd_data = b''
    while True:
        data = conn_sock.recv(32)
        if not data:
            break
        recd_data += data
    print_msg('i', 'Total received: {}'.format(recd_data))

    # Sending the response
    http_msg = make_http_msg()
    remaining = len(http_msg)
    res = 0
    while remaining > 0:
        res = conn_sock.send(http_msg[res:])
        remaining -= res
finally:
    conn_sock.shutdown(socket.SHUT_WR)
    conn_sock.close()
    print_msg('cl', 'The connection closed.')

colored_print.py

colored_print.py


from colorama import Fore, Style


def print_msg(header, msg):
    '''header are i that is INFO or e that is ERROR'''

    if header == 'i':
        print(Fore.GREEN + '[INFO]',
              Style.RESET_ALL + msg)
    elif header == 'e':
        print(Fore.RED + '[ERROR]',
              Style.RESET_ALL + msg)
    elif header == 'ac':
        print(Fore.BLUE + '[ACCEPT]',
              Style.RESET_ALL + msg)
    elif header == 'cn':
        print(Fore.BLUE + '[CONNECT]',
              Style.RESET_ALL + msg)
    elif header == 'cl':
        print(Fore.BLUE + '[CLOSE]',
              Style.RESET_ALL + msg)
    else:
        print(Fore.RED + 'ERROR: header is an invalid value.'
              + Style.RESET_ALL)

browser_app.py

browser_app.py


import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWebEngineWidgets import QWebEngineView as QWebView


class Ui_dialog(object):
    def setupUi(self, dialog, html_source):
        dialog.setObjectName('dialog')
        dialog.resize(1000, 650)
        self.stackedWidget = QtWidgets.QStackedWidget(dialog)
        self.stackedWidget.setGeometry(QtCore.QRect(10, 50, 980, 590))
        self.stackedWidget.setObjectName('stackedWidget')
        self.page_1 = QtWidgets.QWidget()
        self.page_1.setObjectName('page_1')
        self.webView = QWebView(self.page_1)
        self.webView.setGeometry(QtCore.QRect(0, 0, 980, 590))
        self.webView.setObjectName('webView')
        self.stackedWidget.addWidget(self.page_1)
        self.page_2 = QtWidgets.QWidget()
        self.page_2.setObjectName('page_2')
        self.page_2_title = QtWidgets.QLabel(self.page_2)
        self.page_2_title.setGeometry(QtCore.QRect(370, 60, 240, 50))
        font = QtGui.QFont()
        font.setPointSize(24)
        self.page_2_title.setFont(font)
        self.page_2_title.setObjectName('page_2_title')
        self.page_2_label1 = QtWidgets.QLabel(self.page_2)
        self.page_2_label1.setGeometry(QtCore.QRect(435, 230, 110, 22))
        font = QtGui.QFont()
        font.setPointSize(16)
        self.page_2_label1.setFont(font)
        self.page_2_label1.setObjectName('page_2_label1')
        self.page_2_ip = QtWidgets.QLineEdit(self.page_2)
        self.page_2_ip.setGeometry(QtCore.QRect(435, 262, 110, 28))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.page_2_ip.setFont(font)
        self.page_2_ip.setObjectName('page_2_ip')
        self.page_2_label2 = QtWidgets.QLabel(self.page_2)
        self.page_2_label2.setGeometry(QtCore.QRect(468, 310, 42, 16))
        font = QtGui.QFont()
        font.setPointSize(16)
        self.page_2_label2.setFont(font)
        self.page_2_label2.setObjectName('page_2_label2')
        self.page_2_url = QtWidgets.QLineEdit(self.page_2)
        self.page_2_url.setGeometry(QtCore.QRect(335, 336, 310, 28))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.page_2_url.setFont(font)
        self.page_2_url.setObjectName('page_2_url')
        self.page_2_save = QtWidgets.QPushButton(self.page_2)
        self.page_2_save.setGeometry(QtCore.QRect(425, 384, 130, 40))
        font = QtGui.QFont()
        font.setPointSize(18)
        self.page_2_save.setFont(font)
        self.page_2_save.setObjectName('page_2_save')
        self.stackedWidget.addWidget(self.page_2)
        self.url_lineEdit = QtWidgets.QLineEdit(dialog)
        self.url_lineEdit.setGeometry(QtCore.QRect(10, 10, 666, 30))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.url_lineEdit.setFont(font)
        self.url_lineEdit.setObjectName('url_lineEdit')
        self.search_btn = QtWidgets.QPushButton(dialog)
        self.search_btn.setGeometry(QtCore.QRect(670, 10, 90, 30))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.search_btn.setFont(font)
        self.search_btn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        self.search_btn.setObjectName('search_btn')
        self.config_btn = QtWidgets.QPushButton(dialog)
        self.config_btn.setGeometry(QtCore.QRect(780, 10, 60, 30))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.config_btn.setFont(font)
        self.config_btn.setObjectName('config_btn')

        # ----------------------------------------------

        self.url_lineEdit.setText('in preparation')
        self.page_2_title.setText('Setting the DNS')
        self.page_2_label1.setText('IP Address')
        self.page_2_ip.setText('in preparation')
        self.page_2_label2.setText('URL')
        self.page_2_url.setText('in preparation')

        self.webView.setHtml(html_source)

        # ----------------------------------------------

        QtCore.QMetaObject.connectSlotsByName(dialog)


def mybrowser(html_source):
    app = QtWidgets.QApplication(sys.argv)
    dialog = QtWidgets.QDialog()
    ui = Ui_dialog()
    ui.setupUi(dialog, html_source)
    dialog.show()
    sys.exit(app.exec_())

Recommended Posts

HTTP server and HTTP client using Socket (+ web browser) --Python3
I tried web scraping using python and selenium
Create a web map using Python and GDAL
Launch a web server with Python and Flask
Try using Kubernetes Client -Python-
Web scraping using Selenium (Python)
Easy HTTP server with Python
Simple HTTP Server for python
Explosive speed! Using Python Simple HTTP Server for kintone development
Operate your browser using the Selenium Web Driver Python bindings
I made a server with Python socket and ssl and tried to access it from a browser
Turn your Android Smart Phone into a Web Server using python.
Overview of how to create a server socket and how to establish a client socket
Authentication using tweepy-User authentication and application authentication (Python)
Write an HTTP / 2 server in Python
Python3 socket module and socket communication flow
Fastest and strongest web server architecture
I made a Chatbot using LINE Messaging API and Python (2) ~ Server ~
Try using the Python web framework Django (1)-From installation to server startup
Development and deployment of REST API in Python using Falcon Web Framework
Set up a local web server in 30 seconds using python 3's http.server
Start a web server using Bottle and Flask (I also tried using Apache)
I want to make a web application using React and Python flask
Install Python3 and Django on Amazon Linux (EC2) and run your web server
Build a lightweight server in Python and listen for Scratch 2 HTTP extensions
From Python to using MeCab (and CaboCha)
Socket communication and multi-thread processing by Python
Port forwarding your web server using iptables
Using Python and MeCab with Azure Databricks
Socket communication using socketserver with python now
Visualize server resources using InfluxDB and Grafana
Socket communication by C language and Python
Practice web scraping with Python and Selenium
I'm using tox and Python 3.3 with Travis-CI
Put Docker in Windows Home and run a simple web server with Python
[Now] Python beginner tried to implement HTTP client using requests (header operation included)
[Python] How to create a local web server environment with SimpleHTTPServer and CGIHTTPServer
Head orientation estimation using Python and OpenCV + dlib
How to open a web browser from python
Procedure to use TeamGant's WEB API (using python)
Notes on installing Python3 and using pip on Windows7
Python Web Content made with Lolipop cheap server
Python development flow using Poetry, Git and Docker
I tried object detection using Python and OpenCV
Regularly monitor the HTTP response of the web server
Start a simple Python web server with Docker
Effective and simple Web server security measures "Linux"
Try using the Python web framework Tornado Part 1
Pharmaceutical company researchers summarized web scraping using Python
[Python3] Automatic sentence generation using janome and markovify
Try to create an HTTP server using Node.js
Try using tensorflow ① Build python environment and introduce tensorflow
Create a Mac app using py2app and Python3! !!
Try using the Python web framework Tornado Part 2
GRPC starting with Go server and Dart client
Try using ChatWork API and Qiita API in Python
[Python3] Take a screenshot of a web page on the server and crop it further
How to host web app backend processing in Python using a rental server subdomain