Python HTTP Server

1. WSGI

1.1 wsgiref.simple_server

server.py:

1 from wsgiref.simple_server import make_server
2 from WSGI_response import application
3 
4 httpd = make_server('', 8000, application)
5 print 'Listening'
6 httpd.serve_forever()

application.py

 1 def application(environ, start_response):
 2     start_response('200 0k', [('Content-Type', 'text/html')])
 3     # path_info = environ['PATH_INFO'][1:]
 4     return '''<head>
 5     <REQUEST_METHOD>%s
 6     <SCRIPT_NAME>%s
 7     <PATH_INFO>%s
 8     <QUERY_STRING>%s
 9     <CONTENT_TYPE>%s
10     <CONTENT_LENGTH>%s
11     <SERVER_NAME>%s
12     <SERVER_PORT>%s
13     <SERVER_PROTOCOL>%s
14     <X_Storage_User>%s
15     <X_Storage_Pass>%s
16 </head>
17 <path_info>%s'''  %(environ['REQUEST_METHOD'], environ['SCRIPT_NAME'], environ['PATH_INFO'], environ['QUERY_STRING'], environ['CONTENT_TYPE'] ,environ['CONTENT_LENGTH'], environ['SERVER_NAME'], environ['SERVER_PORT'], environ['SERVER_PROTOCOL'], environ.get('X_Storage_User'),environ.get('X_Storage_Pass'),environ['PATH_INFO'][1:])

 

没有获取到自定义的http头,那如何获取自定义http头???待续

 1 2017-03-24 15:17:30 ⌚  meow in ~
 2 ○ → curl -v -H 'X_Storage_User: test:tester' -H 'X_Storage_Pass: testing' http://127.0.0.1:8000/auth
 3 * Hostname was NOT found in DNS cache
 4 *   Trying 127.0.0.1...
 5 * Connected to 127.0.0.1 (127.0.0.1) port 8000 (#0)
 6 > GET /auth HTTP/1.1
 7 > User-Agent: curl/7.35.0
 8 > Host: 127.0.0.1:8000
 9 > Accept: */*
10 > X_Storage_User: test:tester
11 > X_Storage_Pass: testing
12 > 
13 * HTTP 1.0, assume close after body
14 < HTTP/1.0 200 0k
15 < Date: Fri, 24 Mar 2017 07:19:33 GMT
16 < Server: WSGIServer/0.1 Python/2.7.6
17 < Content-Type: text/html
18 < 
19 <head>
20     <REQUEST_METHOD>GET
21     <SCRIPT_NAME>
22     <PATH_INFO>/auth
23     <QUERY_STRING>
24     <CONTENT_TYPE>text/plain
25     <CONTENT_LENGTH>
26     <SERVER_NAME>meow
27     <SERVER_PORT>8000
28     <SERVER_PROTOCOL>HTTP/1.1
29     <X_Storage_User>
30     <X_Storage_Pass>None
31 </head>
32 * Closing connection 0
33 <path_info>auth

 2. Flask

flask主要使用装饰器将URL和application联系起来,如@app.route('/', methods=['GET', 'POST'])

Flask也是基于WSGI的,进一步进行封装.

from flask import Flask
from flask import request

app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def home():
    return 'at home'

@app.route('/signin', methods=['GET'])
def sigin_form():
    return 'input x-auth-user and x-auth-pass'

@app.route('/signin', methods=['POST'])
def signin_auth():
    username = request.headers.get('x-auth-user')
    passwd = request.headers.get('x-auth-pass')
    if username == 'coral' and passwd == '123':
        return 'success\nx-auth-user: %s and x-auth-pass: %s' %(username, passwd)
    else:
        return 'failed\nx-auth-user: %s and x-auth-pass: %s' %(username, passwd)


if __name__ == '__main__':
    app.run()

then:

 2017-03-27 15:42:05 ⌚  meow in ~
○ → curl http://127.0.0.1:5000/
at home
 2017-03-27 15:42:31 ⌚  meow in ~
○ → curl http://127.0.0.1:5000/signininput x-auth-user and x-auth-pass
 2017-03-27 15:42:36 ⌚  meow in ~
○ → curl -X POST -H 'x-auth-user:coral' -H 'x-auth-pass:123' http://127.0.0.1:5000/signin
success
x-auth-user: coral and x-auth-pass: 123
 2017-03-27 15:42:42 ⌚  meow in ~
○ → curl -X POST -H 'x-auth-user:coral' http://127.0.0.1:5000/signinfailed
x-auth-user: coral and x-auth-pass: None

 3. BaseHTTPServer

BaseHTTPServer,就是麻烦了点,要自己解析http请求

 1 #encoding=utf-8
 2 
 3 from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
 4 import io,shutil  
 5 import urllib,time
 6 import getopt,string
 7 
 8 class MyRequestHandler(BaseHTTPRequestHandler):
 9 
10     def handle_request(self):
11         content = ""
12 
13         # 获取http head
14         request = dict()
15         request['X-AUTH-NAME'] = self.headers.get('X-AUTH-NAME', 'null')
16         request['X-AUTH-PASS'] = self.headers.get('X-AUTH-PASS', 'null')
17         
18         # 获取http data
19         data = self.rfile.read(int(self.headers['content-length']))
20         data = urllib.unquote(data).decode("utf-8", 'ignore')  #指定编码方式
21         request['data'] = data
22         return request
23         
24     def response(self, data, code):
25         enc="UTF-8"
26         data = data.encode(enc)
27         f = io.BytesIO()
28         f.write(data)
29         f.seek(0)
30         self.send_response(code)
31         self.send_header("Content-type", "text/html; charset=%s" % enc)
32         self.send_header("Content-Length", str(len(data)))
33         self.end_headers()
34         shutil.copyfileobj(f,self.wfile)
35 
36     def do_GET(self):
37         print 'input X-AUTH-NAME AND X-AUTH-PASS'
38 
39     def do_POST(self):
40         request = self.handle_request()
41         if request['X-AUTH-NAME'] == 'CCC' and request['X-AUTH-PASS'] == '123':
42             self.response('success', 200)
43         else:
44             self.response('failed', 401)
45     
46     def do_PUT(self):
47         print 'put'
48             
49 
50 if __name__=='__main__':
51     try:
52         server = HTTPServer(('', 8000), MyRequestHandler)
53         print 'started httpserver...'
54         server.serve_forever()
55     except KeyboardInterrupt:
56         server.socket.close()
57     pass

then:

2017-03-27 20:41:55 ⌚  meow in ~
○ → curl -v -d "data=postdata" -H 'X-AUTH-NAME:CCC' http://localhost:8000?test=post
* Rebuilt URL to: http://localhost:8000/?test=post
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8000 (#0)
> POST /?test=post HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost:8000
> Accept: */*
> X-AUTH-NAME:CCC
> Content-Length: 13
> Content-Type: application/x-www-form-urlencoded
> 
* upload completely sent off: 13 out of 13 bytes
* Empty reply from server
* Connection #0 to host localhost left intact
curl: (52) Empty reply from server

 2017-03-27 20:42:43 ⌚  meow in ~
○ → curl -v -d "data=postdata" -H 'X-AUTH-NAME:CCC' http://localhost:8000?test=post
* Rebuilt URL to: http://localhost:8000/?test=post
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8000 (#0)
> POST /?test=post HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost:8000
> Accept: */*
> X-AUTH-NAME:CCC
> Content-Length: 13
> Content-Type: application/x-www-form-urlencoded
> 
* upload completely sent off: 13 out of 13 bytes
* HTTP 1.0, assume close after body
< HTTP/1.0 401 Unauthorized
< Server: BaseHTTP/0.3 Python/2.7.6
< Date: Mon, 27 Mar 2017 12:43:35 GMT
< Content-type: text/html; charset=UTF-8
< Content-Length: 6
< 
* Closing connection 0
failed

 4. SimpleHTTPServer

simpleHTTPServer的父类也是BaseHTTPServer.

参考http://www.cnblogs.com/itech/archive/2011/12/31/2308697.html

  1 #!/usr/bin/env python
  2 #coding=utf-8
  3  
  4 import os, sys, platform
  5 import posixpath
  6 import BaseHTTPServer
  7 from SocketServer import ThreadingMixIn
  8 import threading
  9 import urllib
 10 import cgi
 11 import shutil
 12 import mimetypes
 13 import re
 14 import time
 15 
 16 try:
 17     from cStringIO import StringIO
 18 except ImportError:
 19     from StringIO import StringIO
 20      
 21 
 22 
 23 # 请求处理
 24 class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
 25  
 26     def do_GET(self):
 27         # 获取文件内容
 28         f = None
 29         path = self.translate_path(self.path)
 30         if os.path.isdir(path):
 31             if not self.path.endswith('/'):
 32                 # redirect browser - doing basically what apache does
 33                 self.send_response(301)
 34                 self.send_header("Location", self.path + "/")
 35                 self.end_headers()
 36                 return None
 37         try:
 38             f = open(path, 'rb')
 39         except IOError:
 40             self.send_error(404, "File not found")
 41             return None
 42         self.send_response(200)
 43         self.send_header("Content-type", "text/html")
 44         fs = os.fstat(f.fileno())
 45         self.send_header("Content-Length", str(fs[6]))
 46         self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
 47         self.end_headers()
 48         shutil.copyfileobj(f,self.wfile)
 49         f.close()
 50  
 51     def do_HEAD(self):
 52         """列出目录下的所有文件"""
 53         path = self.translate_path(self.path)
 54         # 获取路径下的文件列表
 55         try:
 56             list = os.listdir(path)
 57         except os.error:
 58             self.send_error(404, "No permission to list directory")
 59             return None
 60         list.sort(key=lambda a: a.lower())
 61         # print list
 62         f = StringIO()
 63         displaypath = cgi.escape(urllib.unquote(self.path))
 64         for name in list:
 65             fullname = os.path.join(path, name)
 66             f.write(fullname)
 67             f.write('\n')
 68         length = f.tell()
 69         f.seek(0)
 70         # 发送response head
 71         self.send_response(200)
 72         self.send_header("Content-type", "text/html")
 73         self.send_header("Content-Length", str(length))
 74         self.end_headers()
 75         # 发送response data
 76         shutil.copyfileobj(f,self.wfile)
 77  
 78     def do_PUT(self):
 79         """Serve a POST request."""
 80         r, info = self.put_file()
 81         print r, info, "by: ", self.client_address
 82         f = StringIO()
 83         if r:
 84             f.write("Success:")
 85         else:
 86             f.write("Failed:")
 87         f.write(info)
 88         length = f.tell()
 89         f.seek(0)
 90         self.send_response(200)
 91         self.send_header("Content-type", "text/html")
 92         self.send_header("Content-Length", str(length))
 93         self.end_headers()
 94         if f:
 95             shutil.copyfileobj(f, self.wfile)
 96             f.close()
 97 
 98          
 99     def put_file(self):
100         # 获取上传的内容
101         content = ""
102         remainbytes = int(self.headers['content-length'])
103         
104         line = self.rfile.readline()
105         remainbytes -= len(line)
106         content += line
107         while(remainbytes > 0):
108             line = self.rfile.readline()
109             remainbytes -= len(line)
110             content += line
111         # 创建本地文件
112         savefilepath = self.translate_path(self.path)
113         while os.path.exists(savefilepath):
114             savefilepath += "_"
115         try:
116             out = open(savefilepath, 'wb')
117         except IOError:
118             return (False, "Can't create file to write, do you have permission to write?")
119                  
120         remainbytes = len(content)
121         out.write(content)
122         return (True, "File %s upload success!" %savefilepath)
123 
124     def translate_path(self, path):
125         path = path.split('?',1)[0]
126         path = path.split('#',1)[0]
127         path = posixpath.normpath(urllib.unquote(path))
128         words = path.split('/')
129         words = filter(None, words)
130         path = os.getcwd()
131         for word in words:
132             drive, word = os.path.splitdrive(word)
133             head, word = os.path.split(word)
134             if word in (os.curdir, os.pardir): 
135                 continue
136             path = os.path.join(path, word)
137         return path
138 
139 class ThreadingServer(ThreadingMixIn, BaseHTTPServer.HTTPServer):
140     pass
141  
142 if __name__ == '__main__':
143     # 获取和解析port
144     try:
145         port = int(sys.argv[1])
146     except Exception, e:
147         port = 8080
148     if not 1024 < port < 65535:
149         port = 8080
150     serveraddr = ('', port)
151     print 'listening on port: %d' %(port)
152     #单线程
153     # srvr = BaseHTTPServer.HTTPServer(serveraddr, SimpleHTTPRequestHandler)
154     #多线程
155     srvr = ThreadingServer(serveraddr, SimpleHTTPRequestHandler)
156     srvr.serve_forever()

then:

 2017-03-28 20:59:30 ⌚  meow in ~/Desktop
○ → curl -X HEAD  http://127.0.0.1:8088/
/home/meow/Desktop/python_http/SimpleHTTPServer/S_HTTP_S.py
/home/meow/Desktop/python_http/SimpleHTTPServer/S_HTTP_S.py~
/home/meow/Desktop/python_http/SimpleHTTPServer/S_HTTP_Server.py
/home/meow/Desktop/python_http/SimpleHTTPServer/S_HTTP_Server.py~

 2017-03-28 20:59:35 ⌚  meow in ~/Desktop
○ → curl -v -X PUT -T "1" http://127.0.0.1:8088/
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8088 (#0)
> PUT /1 HTTP/1.1
> User-Agent: curl/7.35.0
> Host: 127.0.0.1:8088
> Accept: */*
> Content-Length: 303
> Expect: 100-continue
> 
* Done waiting for 100-continue
* We are completely uploaded and fine
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Server: BaseHTTP/0.3 Python/2.7.6
< Date: Tue, 28 Mar 2017 12:59:41 GMT
< Content-type: text/html
< Content-Length: 78
< 
* Closing connection 0
Success:File /home/meow/Desktop/python_http/SimpleHTTPServer/1 upload success!
 2017-03-28 20:59:41 ⌚  meow in ~/Desktop
○ → curl -X HEAD  http://127.0.0.1:8088/
/home/meow/Desktop/python_http/SimpleHTTPServer/1
/home/meow/Desktop/python_http/SimpleHTTPServer/S_HTTP_S.py
/home/meow/Desktop/python_http/SimpleHTTPServer/S_HTTP_S.py~
/home/meow/Desktop/python_http/SimpleHTTPServer/S_HTTP_Server.py
/home/meow/Desktop/python_http/SimpleHTTPServer/S_HTTP_Server.py~

 2017-03-28 20:59:47 ⌚  meow in ~/Desktop
○ → curl -v -X GET http://127.0.0.1:8088/1
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8088 (#0)
> GET /1 HTTP/1.1
> User-Agent: curl/7.35.0
> Host: 127.0.0.1:8088
> Accept: */*
> 
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Server: BaseHTTP/0.3 Python/2.7.6
< Date: Tue, 28 Mar 2017 12:59:51 GMT
< Content-type: text/html
< Content-Length: 303
< Last-Modified: Tue, 28 Mar 2017 12:59:41 GMT
< 
除了Flask,常见的Python Web框架还有:

    Django:全能型Web框架;

    web.py:一个小巧的Web框架;

    Bottle:和Flask类似的Web框架;

    Tornado:Facebook的开源异步Web框架。
华为raid2.0白皮书https://wenku.baidu.com/view/92222333336c1eb91a375dc6.html
* Closing connection 0

 5. SOCKET

参考http://www.cnblogs.com/litaozijin/p/6624029.html

WebServer.py:

 1 #!/usr/bin/env python
 2 #coding=utf-8
 3 
 4 import socket
 5 import sys
 6 import getFileContent
 7 
 8 #声明一个将要绑定的IP和端口,这里是用本地地址
 9 server_address = ('localhost', 8088)
10 class WebServer():
11     def run(self):
12         print >> sys.stderr, 'starting up on %s port %s' % server_address
13         #实例化一个Socket,AF_INET是IPV4套接字,SOCK_STREAM是tcp
14         sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
15         #绑定IP和端口
16         sock.bind(server_address)
17         #设置监听
18         sock.listen(1)
19         #这里首先给个死循环,其实这里是需要多线程的,再后续版本将会实现
20         while True:
21             #接受客户端的请求并得到请求信息和请求的端口信息
22             connection, client_address = sock.accept()
23             print >>sys.stderr, 'waiting for a connection'
24             try:
25                 # 获取请求http 头信息
26                 httphead = connection.recv(1024)
27                 # 获取上传数据长度
28                 length = 0
29                 beginsearch = httphead.find("Content-Length: ")
30                 if (beginsearch != -1):
31                     beginsearch += 16
32                     while (httphead[beginsearch:beginsearch+1].isdigit()):
33                         length *= 10
34                         length += int(httphead[beginsearch])
35                         beginsearch += 1
36                 print length
37                 # 获取上传数据内容
38                 inputfile = ''
39                 if length:
40                     inputfile = connection.recv(length)                
41 
42                 if httphead:
43                     # 处理http请求
44                     connection.sendall(getFileContent.server(httphead, inputfile))
45             finally:
46                 connection.close()
47 
48 if __name__ == '__main__':
49     server=WebServer()
50     server.run()

getFileContent.py:

  1 #!/usr/bin/env python
  2 #coding=utf-8
  3 
  4 import sys
  5 import os
  6 
  7 # 处理http请求入口
  8 def server(httphead, inputfile):
  9     # 获取请求类型
 10     msgSendtoClient=""
 11     requestType=httphead[0:httphead.find("/")].rstrip()
 12     if requestType=="GET":
 13         msgSendtoClient=responseGetRequest(httphead,msgSendtoClient)
 14     if requestType=="POST":
 15         msgSendtoClient=responsePostRequest(httphead, inputfile, msgSendtoClient)
 16     return msgSendtoClient
 17 
 18 #打开文件,这里不直接写,二是去取要发送的文件再写
 19 def getFile(msgSendtoClient,file):
 20         for line in file:
 21           msgSendtoClient+=line
 22         return msgSendtoClient
 23 
 24 #筛选出请求的一个方法
 25 def getMidStr(data,startStr,endStr):
 26     startIndex = data.index(startStr)
 27     if startIndex>=0:
 28         startIndex += len(startStr)
 29         endIndex = data.index(endStr)
 30         return data[startIndex:endIndex]
 31 
 32 #获取要发送数据的大小,根据HTTP协议规范,要提前指定发送的实体内容的大小
 33 def getFileSize(fileobject):
 34     fileobject.seek(0,2)
 35     size = fileobject.tell()
 36     return size
 37 
 38 #设置返回的编码格式和文件类型
 39 def setParaAndContext(msgSendtoClient,type,file,openFileType):
 40     msgSendtoClient+="Content-Type: "+type+";charset=utf-8"
 41     
 42     if file == 'null':
 43         # 如果没有说明要获取的文件,则列出文件列表
 44         content = ''
 45         path = os.getcwd()
 46         try:
 47             filelist = os.listdir(path)
 48         except os.error:
 49             return None
 50         for alist in filelist:
 51             content += alist
 52             content += '\n'
 53         msgSendtoClient+="Content-Length: "+str(content)+"\n"+"\n"
 54         msgSendtoClient += content
 55     else:
 56         # 如果说明了要获取的文件,则返回文件内容
 57         msgSendtoClient+="Content-Length: "+str(getFileSize(open(file,"r")))+"\n"+"\n"
 58         htmlFile=open(file,openFileType)
 59         msgSendtoClient=getFile(msgSendtoClient,htmlFile)
 60     return msgSendtoClient
 61 
 62 #GET请求的返回数据
 63 def responseGetRequest(data,msgSendtoClient):
 64     return responseGRTRequest(getMidStr(data,'GET /',' HTTP/1.1'),msgSendtoClient)
 65 
 66 #POST请求的返回数据
 67 def responsePostRequest(data, inputfile, msgSendtoClient):
 68     return responsePOSTRequest(data, inputfile, msgSendtoClient)
 69 
 70 def responsePOSTRequest(httphead, inputfile, msgSendtoClient):
 71     print 'responsePOSTRequest'
 72     print 'httphead:' + httphead
 73     print 'inputfile:' + inputfile
 74     # 获取保存文件名    
 75     filename = httphead[httphead.find("/") + 1:]
 76     filename = filename[0: filename.find(' ')]
 77     print 'filename: %s \n' %(filename)
 78     
 79     # 创建本地文件
 80     savefilepath = os.getcwd() + '/' + filename
 81     while os.path.exists(savefilepath):
 82         savefilepath += "_"
 83     try:
 84         out = open(savefilepath, 'wb')
 85     except IOError:
 86         return (False, "Can't create file to write, do you have permission to write?")
 87     out.write(inputfile)
 88     return ("File %s upload success!" %savefilepath)
 89 
 90 
 91 #请求返回数据
 92 def responseGRTRequest(getRequestPath,msgSendtoClient):
 93     '''head.txt HTTP返回头部
 94        HTTP/1.1 200 OK
 95        Accept-Ranges: bytes 
 96        ETag: W/"269-1482321927478"
 97        Content-Language: zh-CN
 98     '''
 99     headFile=open("head.txt","r")
100     print 'getRequestPath: ' + getRequestPath
101     msgSendtoClient=getFile(msgSendtoClient,headFile)
102     if getRequestPath=="":
103         msgSendtoClient=setParaAndContext(msgSendtoClient,"text/html","null","r")
104     else:
105         rootPath= os.getcwd() + '/' + getRequestPath
106         print rootPath
107         if os.path.exists(rootPath) and os.path.isfile(rootPath):
108             if ".txt" in rootPath:
109                 msgSendtoClient=setParaAndContext(msgSendtoClient,"text/txt",rootPath,"r")
110             if ".html" in rootPath:
111                 msgSendtoClient=setParaAndContext(msgSendtoClient,"text/html",rootPath,"r")
112             if ".gif" in rootPath:
113                 msgSendtoClient=setParaAndContext(msgSendtoClient,"image/gif",rootPath,"rb")
114             if ".doc" in rootPath:
115                 msgSendtoClient=setParaAndContext(msgSendtoClient,"application/msword",rootPath,"rb")
116             if ".mp4" in rootPath:
117                 msgSendtoClient=setParaAndContext(msgSendtoClient,"video/mpeg4",rootPath,"rb")
118             else:
119                 msgSendtoClient=setParaAndContext(msgSendtoClient,"application/others",rootPath,"r")
120         else:
121             print 'no such file'
122             msgSendtoClient += '\n\n \nno such file'
123     return msgSendtoClient

then:

 1  2017-03-29 17:29:11 ⌚  meow in ~/Desktop
 2 ○ → curl -X GET http://127.0.0.1:8088
 3 
 4 1
 5 Untitled Document~
 6 head.txt
 7 getFileContent.py
 8 getFileContent.py~
 9 getFileContent.pyc
10 1__
11 head.txt~
12 1_
13 webServer.py~
14 webServer.py
15 
16  2017-03-29 18:19:20 ⌚  meow in ~/Desktop
17 ○ → curl -X GET http://127.0.0.1:8088/1
18 除了Flask,常见的Python Web框架还有:
19 
20     Django:全能型Web框架;
21 
22     web.py:一个小巧的Web框架;
23 
24     Bottle:和Flask类似的Web框架;
25 
26     Tornado:Facebook的开源异步Web框架。
27 华为raid2.0白皮书https://wenku.baidu.com/view/92222333336c1eb91a375dc6.html
28 
29  2017-03-29 18:19:28 ⌚  meow in ~/Desktop
30 ○ → curl  -X POST -T '1' http://127.0.0.1:8088
31 File /home/meow/Desktop/python_http/socket/1___ upload success!
32  2017-03-29 18:19:38 ⌚  meow in ~/Desktop
33 ○ → curl  -X POST -T '1' http://127.0.0.1:8088/ttt
34 File /home/meow/Desktop/python_http/socket/ttt upload success!
35  2017-03-29 18:19:52 ⌚  meow in ~/Desktop
36 ○ → curl  -X GET  http://127.0.0.1:8088/ttt
37 除了Flask,常见的Python Web框架还有:
38 
39     Django:全能型Web框架;
40 
41     web.py:一个小巧的Web框架;
42 
43     Bottle:和Flask类似的Web框架;
44 
45     Tornado:Facebook的开源异步Web框架。
46 华为raid2.0白皮书https://wenku.baidu.com/view/92222333336c1eb91a375dc6.html
47 
48  2017-03-29 18:20:24 ⌚  meow in ~/Desktop
49 ○ → curl  -X GET  http://127.0.0.1:8088/tttSSS
50 
51  
52 no such file

 

转载于:https://www.cnblogs.com/coralyms/p/6611735.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值