Wed Framework essence

We can think of it this way : be-all Web Applications are essentially one socket Server side , And the user's browser is a socket client . So we can do it ourselves Web The framework .

Customization of semi-finished products wed frame

import socket
sk = socket.socket()
sk.bind(("127.0.0.1", 80))
sk.listen() while True:
conn, addr = sk.accept()
data = conn.recv(8096)
conn.send(b"OK")
conn.close()

so to speak Web The service is essentially an extension of a dozen lines of code . This code is their ancestor .

The user's browser enters the url , Data is sent to the server , What data does the browser send ? How to send ? Who will decide on this ? Your website is the rule , His website follows his rules , The Internet still works ?

therefore , There must be a uniform rule , Let's send a message 、 There is a format for receiving messages , You can't just write .

The rule is HTTP agreement , It is fine for the browser to send the request information later , The server responds to the message , Follow this rule .

HTTP The protocol mainly specifies the communication format between the client and the server , that HTTP How does the protocol specify the message format ?

Let's first print out what message we received on the server side .

import socket
sk = socket.socket()
sk.bind(("127.0.0.1", 80))
sk.listen() while True:
conn, addr = sk.accept()
data = conn.recv(8096)
print(data) # Print out the message from your browser
conn.send(b"OK")
conn.close() # Output b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8080\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nDNT: 1\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=RKBXh1d3M97iz03Rpbojx1bR6mhHudhyX5PszUxxG3bOEwh1lxFpGOgWN93ZH3zv\r\n\r\n'

Then let's take a look at the response information that the browser receives when we visit the official website of the blog Garden .

Response related information can be found in the browser debug window network It's in the TAB .

Click on view source Then it is shown as the following figure :

We found that messages sent and received need to be formatted , Here's what you need to know HTTP It's agreed .

HTTP Protocol is introduced

HTTP The format requirements of the protocol for sending and receiving messages

Every HTTP The request and response follow the same format , One HTTP contain Header and Body Two parts , among Body It's optional . HTTP Responsive Header There is one of them. Content-Type Indicates the content format of the response . Such as text/html Express HTML Webpage .

The first version of customization wed frame

After the above supplementary study , We know that if we want to write it ourselves web server Get serious , We have to let our Web server When replying a message to the client, follow HTTP Protocol rules plus response status lines , In this way, we have achieved a serious Wed The framework .

import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('127.0.0.1', 8000))
sock.listen() while True:
conn, addr = sock.accept()
data = conn.recv(8096)
# Add the response status line to the reply message
conn.send(b"HTTP/1.1 200 OK\r\n\r\n")
conn.send(b"OK")
conn.close()

We've simply demonstrated it in a dozen lines of code web The nature of the frame .

Let's continue to refine our customization web Frame bar !

Different contents are returned according to different paths

Is that the end ? How to make our Web The service is based on URL It's different to return different contents ?

as easy as pie , We can get the request from the request related data URL The path of , Then make a judgment with the path ...

import socket
sk = socket.socket()
sk.bind(("127.0.0.1", 8080)) # binding IP And port
sk.listen() # monitor while 1:
# Waiting for the connection
conn, add = sk.accept()
data = conn.recv(8096) # Receive messages from clients
# from data Take the path
data = str(data, encoding="utf8") # Converts received data of byte type into a string
# Press \r\n Division
data1 = data.split("\r\n")[0]
url = data1.split()[1] # url It's the access path we separate from the messages sent by the browser
conn.send(b'HTTP/1.1 200 OK\r\n\r\n') # Because to follow HTTP agreement , So the status line should also be added to the reply message
# Return different contents according to different paths
if url == "/index/":
response = b"index"
elif url == "/home/":
response = b"home"
else:
response = b"404 not found!" conn.send(response)
conn.close()

according to URL Different paths in return different content

Different contents are returned according to different paths -- Functional version

The above code solves the difference URL The path returns requirements for different content .

But here comes the problem , If there are many paths to judge what to do ? Do we have to write them one by one if Judge ? Of course not. , We have a smarter way .

import socket
sk = socket.socket()
sk.bind(("127.0.0.1", 8080)) # binding IP And port
sk.listen() # monitor # Encapsulates the parts that return different content as functions
def index(url):
s = " This is a {} page !".format(url)
return bytes(s, encoding="utf8") def home(url):
s = " This is a {} page !".format(url)
return bytes(s, encoding="utf8") while 1:
# Waiting for the connection
conn, add = sk.accept()
data = conn.recv(8096) # Receive messages from clients
# from data Take the path
data = str(data, encoding="utf8") # Converts received data of byte type into a string
# Press \r\n Division
data1 = data.split("\r\n")[0]
url = data1.split()[1] # url It's the access path we separate from the messages sent by the browser
conn.send(b'HTTP/1.1 200 OK\r\n\r\n') # Because to follow HTTP agreement , So the status line should also be added to the reply message
# Return different contents according to different paths ,response It's a concrete responder
if url == "/index/":
response = index(url)
elif url == "/home/":
response = home(url)
else:
response = b"404 not found!" conn.send(response)
conn.close()

according to URL Different paths in return different content -- Functional version

Different contents are returned according to different paths -- The advanced version of the function

It looks like the code above is still going to be written one by one if Judge , What do I do ? We still have a way !( As long as the mind does not slip , More ways than problems !)

import socket
sk = socket.socket()
sk.bind(("127.0.0.1", 8080)) # binding IP And port
sk.listen() # monitor # Encapsulates the parts that return different content as functions
def index(url):
s = " This is a {} page !".format(url)
return bytes(s, encoding="utf8") def home(url):
s = " This is a {} page !".format(url)
return bytes(s, encoding="utf8") # Define a url And the actual function to execute
list1 = [
("/index/", index),
("/home/", home),
] while 1:
# Waiting for the connection
conn, add = sk.accept()
data = conn.recv(8096) # Receive messages from clients
# from data Take the path
data = str(data, encoding="utf8") # Converts received data of byte type into a string
# Press \r\n Division
data1 = data.split("\r\n")[0]
url = data1.split()[1] # url It's the access path we separate from the messages sent by the browser
conn.send(b'HTTP/1.1 200 OK\r\n\r\n') # Because to follow HTTP agreement , So the status line should also be added to the reply message
# Return different contents according to different paths
func = None # Define a variable that holds the name of the function to be executed
for i in list1:
if i[0] == url:
func = i[1]
break
if func:
response = func(url)
else:
response = b"404 not found!" # Return specific response messages
conn.send(response)
conn.close()

according to URL Different paths in return different content -- The advanced version of the function

Return to concrete HTML file

Perfect solution to the difference URL Returns questions with different contents . But I don't want to just return a few strings , I want to return the full HTML Content , What should we do ?

That's all right. , Whatever it is , In the end, the data is converted into bytes and sent out . We can open it HTML file , Read out the binary data inside it , It is then sent to the browser .

import socket
sk = socket.socket()
sk.bind(("127.0.0.1", 8080)) # binding IP And port
sk.listen() # monitor # Encapsulates the parts that return different content as functions
def index(url):
# Read index.html Content of page
with open("index.html", "r", encoding="utf8") as f:
s = f.read()
# Return byte data
return bytes(s, encoding="utf8") def home(url):
with open("home.html", "r", encoding="utf8") as f:
s = f.read()
return bytes(s, encoding="utf8") # Define a url And the actual function to execute
list1 = [
("/index/", index),
("/home/", home),
] while 1:
# Waiting for the connection
conn, add = sk.accept()
data = conn.recv(8096) # Receive messages from clients
# from data Take the path
data = str(data, encoding="utf8") # Converts received data of byte type into a string
# Press \r\n Division
data1 = data.split("\r\n")[0]
url = data1.split()[1] # url It's the access path we separate from the messages sent by the browser
conn.send(b'HTTP/1.1 200 OK\r\n\r\n') # Because to follow HTTP agreement , So the status line should also be added to the reply message
# Return different contents according to different paths
func = None # Define a variable that holds the name of the function to be executed
for i in list1:
if i[0] == url:
func = i[1]
break
if func:
response = func(url)
else:
response = b"404 not found!" # Return specific response messages
conn.send(response)
conn.close()

Go back to independent HTML page

Make your web page dynamic

This page can show , But it's all static . The content of the page will not change , What I want is a dynamic website .

That's all right. , I also have a way to solve . I chose to use string substitution to fulfill this requirement .( Here we use timestamps to simulate dynamic data )

import socket
import time sk = socket.socket()
sk.bind(("127.0.0.1", 8080)) # binding IP And port
sk.listen() # monitor # Encapsulates the parts that return different content as functions
def index(url):
with open("index.html", "r", encoding="utf8") as f:
s = f.read()
now = str(time.time())
s = s.replace("@@oo@@", now) # Define special symbols in web pages , Use dynamic data to replace pre-defined special symbols
return bytes(s, encoding="utf8") def home(url):
with open("home.html", "r", encoding="utf8") as f:
s = f.read()
return bytes(s, encoding="utf8") # Define a url And the actual function to execute
list1 = [
("/index/", index),
("/home/", home),
] while 1:
# Waiting for the connection
conn, add = sk.accept()
data = conn.recv(8096) # Receive messages from clients
# from data Take the path
data = str(data, encoding="utf8") # Converts received data of byte type into a string
# Press \r\n Division
data1 = data.split("\r\n")[0]
url = data1.split()[1] # url It's the access path we separate from the messages sent by the browser
conn.send(b'HTTP/1.1 200 OK\r\n\r\n') # Because to follow HTTP agreement , So the status line should also be added to the reply message
# Return different contents according to different paths
func = None # Define a variable that holds the name of the function to be executed
for i in list1:
if i[0] == url:
func = i[1]
break
if func:
response = func(url)
else:
response = b"404 not found!" # Return specific response messages
conn.send(response)
conn.close()

Make your web page dynamic

Okay , Stop here first ..

Server programs and applications

For real development python web Procedure , It's usually divided into two parts : Server programs and applications .

The server program is responsible for that socket Server encapsulation , And when the request comes , Collate the various data requested .

The application is responsible for the specific logical processing . In order to facilitate the development of the application , There are many Web frame , for example :Django、Flask、web.py etc. . Different frameworks are developed in different ways , But anyway , The developed application program should cooperate with the server program , To provide services to users .

such , Server programs need different support for different frameworks . Such a chaotic situation is not only for servers, but also for frameworks , All bad . For servers , Need to support different frameworks , For the framework , Only the server that supports it can be used by the developed application .

Now , Standardization becomes particularly important . We can set a standard , As long as the server program supports this standard , The framework also supports this standard , Then they can use it together . Once the criteria are set , Mutual realization . such , The server can support more standard frameworks , The framework can also use more servers that support standards .

WSGI(Web Server Gateway Interface) It's a norm , It defines usage Python Compiling web Application and web Interface format between server programs , Realization web Application and web Decoupling between server programs .

frequently-used WSGI The server has uwsgi、Gunicorn. and Python Standard library provides independence WSGI The server name wsgiref,Django The development environment uses this module to make the server .

Continue from here ...

wsgiref

We make use of wsgiref Module to replace what we wrote ourselves web Framework of the socket server part :

"""
according to URL Different paths in return different content -- The advanced version of the function
return HTML page
Make your web page dynamic
wsgiref Module version
""" import time
from wsgiref.simple_server import make_server # Encapsulates the parts that return different content as functions
def index(url):
with open("index.html", "r", encoding="utf8") as f:
s = f.read()
now = str(time.time())
s = s.replace("@@oo@@", now)
return bytes(s, encoding="utf8") def home(url):
with open("home.html", "r", encoding="utf8") as f:
s = f.read()
return bytes(s, encoding="utf8") # Define a url And the actual function to execute
list1 = [
("/index/", index),
("/home/", home),
] def run_server(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ]) # Set up HTTP Response status code and header information
url = environ['PATH_INFO'] # Get the input from the user url
func = None
for i in list1:
if i[0] == url:
func = i[1]
break
if func:
response = func(url)
else:
response = b"404 not found!"
return [response, ] if __name__ == '__main__':
httpd = make_server('127.0.0.1', 8090, run_server)
print(" I am here 8090 Wait for you ...")
httpd.serve_forever()

wsgiref Module version

jinja2

The above code implements a simple dynamic , I can query the data from the database , Then replace me html The corresponding content in , Then send it to the browser to finish rendering . This process is equivalent to HTML Template render data . It's essentially HTML Some special symbols are used in the content to replace the data to be displayed . The special symbol I use here is what I define , In fact, template rendering has a ready-made tool : jinja2

download jinja2:

pip install jinja2
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="x-ua-compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Title</title>
</head>
<body>
<h1> full name :{{name}}</h1>
<h1> hobby :</h1>
<ul>
{% for hobby in hobby_list %}
<li>{{hobby}}</li>
{% endfor %}
</ul>
</body>
</html>

index2.html file

Use jinja2 Rendering index2.html file :

from wsgiref.simple_server import make_server
from jinja2 import Template def index():
with open("index2.html", "r") as f:
data = f.read()
template = Template(data) # Generate template file
ret = template.render({"name": "Alex", "hobby_list": [" Hot head ", " Go to the bar "]}) # Fill the data into the template
return [bytes(ret, encoding="utf8"), ] def home():
with open("home.html", "rb") as f:
data = f.read()
return [data, ] # Define a url The correspondence with the function
URL_LIST = [
("/index/", index),
("/home/", home),
] def run_server(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ]) # Set up HTTP Response status code and header information
url = environ['PATH_INFO'] # Get the input from the user url
func = None # The function to be executed
for i in URL_LIST:
if i[0] == url:
func = i[1] # Defined before going url Look for... In the list url The function that should be executed
break
if func: # If you can find the function to execute
return func() # Returns the execution result of the function
else:
return [bytes("404 There is no such page ", encoding="utf8"), ] if __name__ == '__main__':
httpd = make_server('', 8000, run_server)
print("Serving HTTP on port 8000...")
httpd.serve_forever()

Now the data is handwritten by ourselves , Can you query the data from the database , To fill in the page ?

Use pymysql Connect to database :

conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", passwd="xxx", db="xxx", charset="utf8")
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute("select name, age, department_id from userinfo")
user_list = cursor.fetchall()
cursor.close()
conn.close()

Create a test of user surface

CREATE TABLE user(
id int auto_increment PRIMARY KEY,
name CHAR(10) NOT NULL,
hobby CHAR(20) NOT NULL
)engine=innodb DEFAULT charset=UTF8;

The principle of templates is string substitution , All we have to do is HTML Follow... On the page jinja2 The rules of grammar say , Its internal will be replaced according to the specified syntax , So as to achieve dynamic return content .

Customize Wed More articles on Framework

  1. Customize MVC frame

    We're learning to customize MVC It's often heard when framing Model1 ,Model2 and MVC. So what is Model1 What is? Model2 What is MVC Well ? What is? Model1? Model1 It's a pure jsp Development technology ...

  2. Struts2 Customize MVC frame

    One .Model1 And Model2: Model1: It's a pure jsp Development technology , Mix business logic code with view rendering code . Model2:Model2 Is in Model1 On the basis of , Separate the code of business logic , Isolated form ...

  3. JDBC Learning notes ( Four )—— Customize JDBC frame +Apache—DBUtils frame + Business management + Operate multiple tables

    Contents of this article :       1. Customize JDBC frame  —— Database metadata :DataBaseMetaData        2. Customize JDBC frame  —— Database metadata :DataBaseMetaData       ...

  4. 【Electron】Electron Introduction to development ( 8、 ... and ): Customize electron Frame shell (shell) Menu for (Menu)

    1. Customize electron Frame shell (shell) Menu for (Menu) electron Of main.js Li code : const Menu = require('electron').Menu; var te ...

  5. Chapter one Customize MVC frame

    Chapter one   Customize MVC frame 1.1 MVC Pattern design      form :Model: Model , For data and business processing           View : View , For data display           Controller: controller ...

  6. web The nature and customization of the framework web frame Template rendering jinja2 mvc and mtv frame Django Download and install the framework be based on Django A simple example of implementation

    Django Foundation one web The nature of the frame Contents of this section One web The nature and customization of the framework web frame Two Template rendering JinJa2 3、 ... and MVC and MTV frame Four Django Download and install 5、 ... and be based on Django A simple implementation ...

  7. Customize MVC The tool class of framework - Model class

    So far, it has been transformed 5 Classes : ubuntu: By encapsulating the captcha library, you can install it step by step php Of gd Expand Customize MVC The tool class of framework - Encapsulation of paging class Customize MVC The tool class of framework - File upload class Customize MVC The tool class of framework - The image processing ...

  8. Customize MVC The tool class of framework - Image processing class

    So far, it has been transformed 4 Classes : ubuntu: By encapsulating the captcha library, you can install it step by step php Of gd Expand Customize MVC The tool class of framework - Encapsulation of paging class Customize MVC The tool class of framework - File upload class Image processing class : 1, Image watermark processing ( ...

  9. Customize MVC The tool class of framework - File upload class

    So far, it has been transformed 3 Classes : ubuntu: By encapsulating the captcha library, you can install it step by step php Of gd Expand Customize MVC The tool class of framework - Encapsulation of paging class The file upload function is as follows : 1, Allows you to customize the type of file you upload , file mime Information , writing ...

Random recommendation

  1. How to safely shut down MySQL example

    How to safely shut down MySQL example Reprinted from :http://imysql.com/2014/08/13/mysql-faq-howto-shutdown-mysqld-fulgraceful.shtml this paper ...

  2. web form The basic knowledge is sorted out

    WebForm Basic knowledge of 1.(IIS7 The standard home page of iisstart.htm)ASP.NET yes .NET The technology of developing web applications , There are two ways ,1.webform : For example, Taobao. 2.MVC B/S A kind of net ...

  3. machine learning ——SVM Detailed explanation ( Standard form , Dual form ,Kernel And Soft Margin)

    ( Write it at the front : Machine learning is fast 2 Years. , More or less used some algorithms , But it's a waste of time to knock on the formula , So I've been shelving starting a machine learning series blog . But now, after all, is the age of electronics , It's impossible to carry your own notepad with you all the time . If you can take out your hand ...

  4. Backup VPS Get the content to China

    origin : Recently, I'm going to start a topic , Campus network has entered the stage of charging test , We need to get the vehicle database down Come down . Found in China down It's really slow . So I used the VPS Come on down, Sure enough ,30M About the download speed ...

  5. my97 Custom events

    onFocus="WdatePicker({onpicked:function(){alert(0);}})"

  6. Word Directly publish Sina blog ( With Wo…

    Original address :Word Directly publish Sina blog ( With Word 2013 For example ) author :paulke2011 Be careful : This blog is written directly by Word 2013 issue ! It's a tutorial, though , But it's more of an experiment . I have known for a long time Word Yes ...

  7. assignment , When to use value, When to use innerText

    Assignment statement : window.document.getElementById('limittime').value='${date}' window.document.getElementById('li ...

  8. k8s And Hello World( Four )

    example :Guestbook Message board system will go through Pod.RC.Service And so on , After successful startup, a “Hello World” Leaving a message. . Its system architecture is based on PHP+Redis Distributed Web Should be ...

  9. file &amp; Report status ID

    def_filestatus Uploading=4 WaitingParse=6 Parsing=10 Completed=14 ParseError=1006 UploadError=1004 d ...

  10. When Java encounter XML The encounter of +dom4j

    XML brief introduction : XML: Extensible markup language ! 01. Much like the html 02. The focus is on data preservation 03. No need to precompile 04. accord with W3C standard Scalable : We can customize it , Follow your own rules ! Mark : Letters that computers can recognize ...