伺服器(server)根據[維基百科定義](https://zh.wikipedia.org/zh-tw/%E6%9C%8D%E5%8A%A1%E5%99%A8#%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%88%86%E7%B1%BB%EF%BC%88%E8%BD%AF%E4%BB%B6%EF%BC%89),為提供服務的電腦軟體,根據軟體種類可分為:
- 檔案伺服器: NAS儲存裝置...
- 網頁伺服器: Apache...
- 資料庫伺服器: MySQL, MongoDB...
建置正式的伺服器需要諸多考量和維護;如果想檢查網頁專案的目前成果,或簡單分享電腦資源給其他協作者的話,可以透過python建立臨時的網頁伺服器。
在指定目錄內包含`index.html`就能預覽網頁,若沒有則會顯示當前資料夾結構。以下使用 `http.server` 模組建立靜態網頁伺服器
## http.server 產生靜態伺服器
**注意:Python2 和 Python3 使用的模組不同,這裡介紹的為適用於Python3套件與使用方式**
### 下載並引入套件
```
pip install httpserver
import http.server
from http.server import SimpleHTTPRequestHandler, HTTPServer
```
還需多引入兩個物件: `SimpleHTTPRequestHandler` 和 `HTTPServer` 下面會簡單介紹他們的功能
### 最簡單的建置伺服器程式碼
```
## example code to create and run the server from python docs
def run(server_class=HTTPServer, handler_class=BaseHTTPRequestHandler):
server_address = ('', 8000)
httpd = server_class(server_address, handler_class)
httpd.serve_forever()
```
### HTTPServer 和 SimpleHTTPRequestHandler
`HTTPServer` 為socketserver.TCPServer的子類別,能建立一個伺服器實例
還需要給個 `RequestHandlerClass` 向HTTP提出請求與回應,有以下三種:
- BaseHTTPRequestHandler
- SimpleHTTPRequestHandler: 讀取與發佈當前目錄 (比較多人用此object)
- CGIHTTPRequestHandler
最後給個協定版本(protocol)
```
HandlerClass = SimpleHTTPRequestHandler
ServerClass = HTTPServer
Protocol = "HTTP/1.0"
```
:star2: Handler 是什麼?

圖片引用自: https://blog.csdn.net/weixin_62079735/article/details/132797418
輸入伺服器相關資訊,包含ip位址,指定port(預設8000)等,並存為`httpd`變數
```
if sys.argv[1:]:
port = int(sys.argv[1])
else:
port = 8000
server_address = ('127.0.0.1', port)
HandlerClass.protocol_version = Protocol
## standard formula: ip + port + handlerclass
httpd = ServerClass(server_address, HandlerClass)
```
實體化與運作伺服器 `serve_forever()`可以透過 `shutdown()` 關閉
```
sa = httpd.socket.getsockname() ## ('127.0.0.1' 8000)
print ("Serving HTTP on", sa[0], "port", sa[1], "...")
httpd.serve_forever()
```
console 顯示 GET ... 200 代表請求成功
```
Serving HTTP on 127.0.0.1 port 8000 ...
127.0.0.1 - - "GET / HTTP/1.1" 200 -
```
最後打開瀏覽器,輸入 `http://127.0.0.1:8000/` 或是 `http://${your_ip}:8000/` 就可看到成果了
### 完整 co
```
# pip install httpserver
import sys
import http.server
from http.server import SimpleHTTPRequestHandler, HTTPServer
HandlerClass = SimpleHTTPRequestHandler
ServerClass = HTTPServer
Protocol = "HTTP/1.0"
if sys.argv[1:]:
port = int(sys.argv[1])
else:
port = 8000
server_address = ('127.0.0.1', port)
HandlerClass.protocol_version = Protocol
httpd = ServerClass(server_address, HandlerClass)
sa = httpd.socket.getsockname() ## ('127.0.0.1' 8000)
print ("Serving HTTP on", sa[0], "port", sa[1], "...")
httpd.serve_forever()
## it will print 127.0.0.1 - - "GET / HTTP/1.1" 200 - on console
## <-> to shutdown()
```
### 觀看 html 效果
拿出之前寫的index.html 並放在指定路徑,透過 httpserver 產生 localhost 查看 html 網頁,若沒有 html 會顯示本機資料夾結構,可以透過這個方式與人分享網址,查看本機儲存的檔案內容
## 動態伺服器與網路框架
網頁包含動態資訊如資料庫串接,自定義的網頁跳轉等,可利用python `flask` 達成。此模組提供伺服器端的網頁框架,協助高效率架設網站。
### 下載與引入套件
這裡先引入最基本的 `Flask` 其他常用函數(`redirect, url_for, send_from_directory...`)會在後面介紹
```
#pip install Flask
from flask import Flask
```
### 簡單的範例
- create `app.py`
```
# save this as app.py
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello, World!"
if __name__ == '__main__':
app.debug = True ## not shown in formal case
app.run()
```
- 在 `app.py` 同層路徑下執行 `flask run` flask 會生成網頁於 http://127.0.0.1:5000/
### 名詞和概念筆記
- flask 內含有 httpserver,但僅適合測試用,正式發布會建議用 **WSGI server**
- 裝飾器(decorator): `@app.route` 做為路由,紀錄 URL/HTTP動作 與其對應的處理函式
- `@app.route('/')` 這裡的 `/` 代表 http://127.0.0.1:5000/ 這個URL
- 若連結到此網址,會執行 hello() 函數並在網頁印出 Hello, World!
- 若今天還有其他路由如下,打開 http://127.0.0.1:5000/**page/5** 就會看到函式執行結果
```
app.route('/page/5')
def welcome():
return "Welcome"
```
- flask 可以吃URL變數,方法為 `<variable_name>`
### flask 函式 `url_for` `redirect`
`url_for()` 可以讓路由具有追蹤彈性,並搭配 `redirect()` 跳轉網頁
下面例子可知: http://127.0.0.1:5000/b 會被引導回 http://127.0.0.1:5000/
```
from flask import url_for, redirect
@app.route('/')
def hello():
return 'hello'
@app.route('/b')
def b():
return redirect(url_for('hello'))
```
其他套件如結合 html css 模板的`render_template`,或是上傳下載檔案的 `send_from_directory` 會在下篇介紹我的side project時補上~
## References
https://docs.python.org/3/library/http.server.html#
https://chwang12341.medium.com/coding%E8%B5%B7%E4%BE%86-python-%E4%B8%80%E8%A1%8C%E6%8C%87%E4%BB%A4%E5%B0%B1%E8%83%BD%E8%BC%95%E9%AC%86%E5%BB%BA%E7%AB%8B%E7%B6%B2%E9%A0%81%E4%BC%BA%E6%9C%8D%E5%99%A8-simplehttpserver%E5%A5%97%E4%BB%B6-http-server%E4%BD%BF%E7%94%A8%E6%95%99%E5%AD%B8-34c30b81c26
https://hackmd.io/@peterju/B18gmJ7Ph#15Flask-%E7%B6%B2%E9%A0%81%E6%A1%86%E6%9E%B6
https://medium.com/@charming_rust_oyster_221/%E4%BD%BF%E7%94%A8-flask-%E5%89%B5%E5%BB%BA-web-api-%E7%AD%86%E8%A8%98-b5618543632e
https://medium.com/@charming_rust_oyster_221/flask-%E6%AA%94%E6%A1%88%E4%B8%8A%E5%82%B3%E5%88%B0%E4%BC%BA%E6%9C%8D%E5%99%A8%E7%9A%84%E6%96%B9%E6%B3%95-1-c11097c23137
https://hackmd.io/@shaoeChen/HJiZtEngG/https%3A%2F%2Fhackmd.io%2Fs%2FSyP4YEnef