Why is there a web framework
With the previous content, static, Dynamic Web server implementation, has mastered the client request to the server processing mechanism. In dynamic resource processing, the import module is applied according to the request. PY, and then the app portal is invoked to implement dynamic processing. However, in real projects, there must be many applications (. py files), according to this processing mechanism (each application to write a portal, set the status code, headers) does not conform to the architectural design principles, this part is certainly reusable, the application should be a common portal, which introduces a conceptual web framework.
Design ideas
- Extract the Entry application (env,start_response) from each application to the Web server and then distribute it in the portal through the routing mechanism to each application.
The code is as follows:-webframework.py
' # coding:utf-8import timefrom mywebserver Import webserverhtml_root_dir = "./static" Class Application (Object): "' Custom Pass Use the web framework ' # to initialize the routing information Def __init__ (self,urls): Self.urls = URLs # match route def __call__ (self, env, start_res Ponse): Path = Env.get ("Path_info", "/") #/static/index.html if Path.startswith ("/static"): file_name = path[7:] # Open file, read content try:file = open (Html_root_dir + file_name, "RB") Except IOError: # indicates no routing information found, 404 error status = "404 Not Found" header s = [] start_response (status, headers) return "not Found" Else:fi Le_data = File.read () file.close () status = "OK" headers = [] Start_response (status, headers) return File_data.decode ("Utf-8") for Url,handler in Self.urls: If path = = URL: Return Handler (env,start_response) # does not match to status = ' 404 Not Found ' headers = [] Start_response (status,headers) return ' not Found ' def Showtime (env,start_response): status = ' OK ' Heade rs = [(' Content-type ', ' Text/plain ')] start_response (status, headers) return str (Time.time ()) def Sayhell O (env,start_response): status = ' $ OK ' headers = [(' Content-type ', ' Text/plain ')] Start_response (STA Tus,headers) return ' Say hello ' def helloworld (env,start_response): status = ' OK ' headers =[(' content- Type ', ' Text/plain ')] Start_response (status,headers) return ' Hello world ' if __name__ = = ' __main__ ': urls = [ ('/', Showtime), ('/sayhello ', SayHello), ('/helloworld ', HelloWorld)] app = Application (URLs) WebServer = WebServer (APP) Webserver.bind (8000) Webserver.start () '
-mywebserver.py
' # coding:utf-8import Socketimport reimport sysfrom multiprocessing Import processhtml_root_dir = './static ' WSGI_PY = './ Wsgipy ' class WebServer (object): ' Simple WebServer ' def __init__ (self,application): ' Application: Frame ' ' Self.sock_server = Socket.socket (socket.af_inet, socket. SOCK_STREAM) self.sock_server.setsockopt (socket. Sol_socket, SOCKET. SO_REUSEADDR, 1) self.app = Application def start (self): Self.sock_server.listen (+) while True: sock_client, addr = Self.sock_server.accept () print (' [%s,%s] user connected ... '% addr) Handle_c lient_process = Process (Target=self.handle_client, args= (Sock_client,)) Handle_client_process.start () Sock_client.close () def start_response (self, status, headers): "" status = "OK" headers = [("Content-type", "Text/plain")] Star "" "Resp_he Aders = ' http/1.1 ' + status + ' \ r \ n ' for header in Headers:resp_headers + = '%s:%s\r\n '% header self. Resp_headers = Resp_headers def handle_client (self, sock_client): ' Processing client request ' Recv_data = SOCK_CLIENT.R ECV (1024x768) #print (' Request data: ', recv_data) Req_lines = recv_data.splitlines () #for line in Req_lines: # print (line) Req_start_line = Req_lines[0] #print (Req_start_line.decode (' Utf-8 ')) file_name = R E.match (r "\w+ + (/[^]*)", Req_start_line.decode ("Utf-8")). Group (1) method = Re.match (r "(\w+) +/[^]*", Req_start_ Line.decode ("Utf-8")). Group (1) env = {"Path_info": file_name, "Method": Method} Response_body = Self.app (env, self.start_response) response = self.resp_headers + "\ r \ n" + response_body # Return response data to client Sock_client.send (bytes (response, "Utf-8") # Close Client Connection sock_client.close () def bind (sel F, Port): self.soCk_server.bind ((", Port)) def main (): Sys.path.insert (1,wsgi_py) webServer = WebServer () webserver.bind (8000) Webserver.start () if __name__ = = ' __main__ ': Main () '
Start
Entrance is really webframework.py, start the file directly, the client requests the specified path to see the effect. But for most of the framework is started through the command line, we can not start in the program so, and for webserver is always not become, change is the web framework, so the transformation to command line startup, the code is as follows:
-webframework.py
' # Coding:utf-8import Timehtml_root_dir = './static ' class Application (object): ' Custom generic Web framework ' # Initialize routing information def __ Init__ (self,urls): Self.urls = URLs # matching route def __call__ (self, env, start_response): Path = Env.get ("PA Th_info ","/") #/static/index.html if Path.startswith ("/static "): file_name = path[7:] # Open file, read content try:file = open (Html_root_dir + file_name, "RB") except IOError: # indicates no routing information found, 404 error status = "404 Not Found" headers = [] Start_respo NSE (status, headers) return "not found" Else:file_data = File.read () File.close () status = "OK" headers = [] Start_response (Status, header s) return File_data.decode ("Utf-8") for Url,handler in self.urls:if path = = URL: Return Handler (ENv,start_response) # mismatch to status = ' 404 Not Found ' headers = [] Start_response (Status,headers) Return ' not Found ' def Showtime (env,start_response): status = ' OK ' headers = [(' Content-type ', ' t Ext/plain ')] start_response (status, headers) return str (Time.time ()) def SayHello (env,start_response): status = ' OK ' headers = [(' Content-type ', ' Text/plain ')] Start_response (status,headers) return ' Say hello ' Def HelloWorld (env,start_response): status = ' $ OK ' headers =[(' Content-type ', ' Text/plain ')] Start _response (status,headers) return ' Hello world ' urls = [('/', Showtime), ('/sayhello ', SayHello), ('/helloworld ') , HelloWorld)]app = Application (URLs) # if __name__ = = ' __main__ ': # urls = [# ('/', Showtime), # ('/sayhe Llo ', SayHello), # ('/helloworld ', HelloWorld) #]# app = Application (URLs) # # webServer = WebServer (APP) # Webserver.bind (8000)# Webserver.start () '
-mywebserver.py
' # coding:utf-8import Socketimport reimport sysfrom multiprocessing Import processhtml_root_dir = './static ' WSGI_PY = './ Wsgipy ' class WebServer (object): ' Simple WebServer ' def __init__ (self,application): ' Application: Frame ' ' Self.sock_server = Socket.socket (socket.af_inet, socket. SOCK_STREAM) self.sock_server.setsockopt (socket. Sol_socket, SOCKET. SO_REUSEADDR, 1) self.app = Application def start (self): Self.sock_server.listen (+) while True: sock_client, addr = Self.sock_server.accept () print (' [%s,%s] user connected ... '% addr) Handle_c lient_process = Process (Target=self.handle_client, args= (Sock_client,)) Handle_client_process.start () Sock_client.close () def start_response (self, status, headers): "" status = "OK" headers = [("Content-type", "Text/plain")] Star "" "Resp_he Aders = ' http/1.1 ' + status + ' \ r \ n ' for header in Headers:resp_headers + = '%s:%s\r\n '% header self. Resp_headers = Resp_headers def handle_client (self, sock_client): ' Processing client request ' Recv_data = SOCK_CLIENT.R ECV (1024x768) #print (' Request data: ', recv_data) Req_lines = recv_data.splitlines () #for line in Req_lines: # print (line) Req_start_line = Req_lines[0] #print (Req_start_line.decode (' Utf-8 ')) file_name = R E.match (r "\w+ + (/[^]*)", Req_start_line.decode ("Utf-8")). Group (1) method = Re.match (r "(\w+) +/[^]*", Req_start_ Line.decode ("Utf-8")). Group (1) env = {"Path_info": file_name, "Method": Method} Response_body = Self.app (env, self.start_response) response = self.resp_headers + "\ r \ n" + response_body # Return response data to client Sock_client.send (bytes (response, "Utf-8") # Close Client Connection sock_client.close () def bind (sel F, Port): self.soCk_server.bind ((", Port)) def main (): Sys.path.insert (1,wsgi_py) If Len (SYS.ARGV) < 2:sys.exit (" Python My webserver.py Module:app ") module_name, app_name = Sys.argv[1].split (': ') m = __import__ (module_name) app = Getatt R (m,app_name) WebServer = WebServer (APP) Webserver.bind (8000) Webserver.start () if __name__ = = ' __main__ ': main ()`
Invocation mode
On the command line, execute the following command to start the Webserver service, module name: Application framework name, where the app refers to an instance of the application class in webframework.py, which is actually an instance of the application framework. When you follow a custom frame, you can call it directly.
`python MyWebServer.py WebFramework:app `
Code has been uploaded into Github:python applet
Introduction of Web Frameworks