Django學習 之 HTTP與WEB爲Django作準備

一.HTTP

1.HTTP 簡介

HTTP協議(HyperText Transfer Protocol,超文本傳輸協議)是因特網上應用最爲普遍的一種網絡傳輸協議,全部的WWW文件都必須遵照這個標準。html

HTTP是一個基於TCP/IP通訊協議來傳遞數據(HTML 文件, 圖片文件, 查詢結果等)。java

2.HTTP 工做原理

HTTP是基於客戶/服務器模式,且面向鏈接的。典型的HTTP事務處理有以下的過程: [8]
(1)客戶與服務器創建鏈接;
(2)客戶向服務器提出請求;
(3)服務器接受請求,並根據請求返回相應的文件做爲應答;
(4)客戶與服務器關閉鏈接。
客戶與服務器之間的HTTP鏈接是一種一次性鏈接,它限制每次鏈接只處理一個請求,當服務器返回本次請求的應答後便當即關閉鏈接,python

下次請求再從新創建鏈接。這種一次性鏈接主要考慮到WWW服務器面向的是Internet中成幹上萬個用戶,且只能提供有限個鏈接,web

故服務器不會讓一個鏈接處於等待狀態,及時地釋放鏈接能夠大大提升服務器的執行效率。編程

 

Web服務器有:Apache服務器,IIS服務器(Internet Information Services)等。瀏覽器

HTTP默認端口號爲80,可是你也能夠改成8080或者其餘端口。緩存

HTTP三點注意事項:服務器

(1)HTTP是無鏈接:無鏈接的含義是限制每次鏈接只處理一個請求。服務器處理完客戶的請求,並收到客戶的應答後,即斷開鏈接。採用這種方式能夠節省傳輸時間。網絡

(2)HTTP是媒體獨立的:這意味着,只要客戶端和服務器知道如何處理的數據內容,任何類型的數據均可以經過HTTP發送。客戶端以及服務器指定使用適合的MIME-type內容類型。架構

(3)HTTP是無狀態:HTTP協議是無狀態協議。無狀態是指協議對於事務處理沒有記憶能力。缺乏狀態意味着若是後續處理須要前面的信息,則它必須重傳,這樣可能致使每次鏈接傳送的數據量增大。另外一方面,在服務器不須要先前信息時它的應答就較快。

如下圖表展現了HTTP協議通訊流程:

3.HTTP 消息結構

HTTP是基於客戶端/服務端(C/S)的架構模型,經過一個可靠的連接來交換信息,是一個無狀態的請求/響應協議。

一個HTTP"客戶端"是一個應用程序(Web瀏覽器或其餘任何客戶端),經過鏈接到服務器達到向服務器發送一個或多個HTTP的請求的目的。

一個HTTP"服務器"一樣也是一個應用程序(一般是一個Web服務,如Apache Web服務器或IIS服務器等),經過接收客戶端的請求並向客戶端發送HTTP響應數據。

HTTP使用統一資源標識符(Uniform Resource Identifiers, URI)來傳輸數據和創建鏈接。

一旦創建鏈接後,數據消息就經過相似Internet郵件所使用的格式[RFC5322]和多用途Internet郵件擴展(MIME)[RFC2045]來傳送。

(1)客戶端請求消息

客戶端發送一個HTTP請求到服務器的請求消息包括如下格式:請求行(request line)、請求頭部(header)、空行和請求數據四個部分組成,下圖給出了請求報文的通常格式。

(2)服務器響應消息

HTTP響應也由四個部分組成,分別是:狀態行、消息報頭、空行和響應正文。

(3)請求實例

下面實例是一點典型的使用GET來傳遞數據的實例:

客戶端請求:

GET / HTTP/1.1

Host: 127.0.0.1:8888

Connection: keep-alive\r\nCache-Control: max-age=0

Upgrade-Insecure-Requests: 1

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3

Accept-Encoding: gzip, deflate, br

Accept-Language: zh-CN,zh;q=0.9

 

'

HTTP默認的請求方法就是GET

     * 沒有請求體

     * 數據量有限制!

     * GET請求數據會暴露在瀏覽器的地址欄中

 

GET請求經常使用的操做:

       1. 在瀏覽器的地址欄中直接給出URL,那麼就必定是GET請求

       2. 點擊頁面上的超連接也必定是GET請求

       3. 提交表單時,表單默認使用GET請求,但能夠設置爲POST

 

請求頭:

一、Host

請求的web服務器域名地址

二、User-Agent

HTTP客戶端運行的瀏覽器類型的詳細信息。經過該頭部信息,web服務器能夠判斷出http請求的客戶端的瀏覽器的類型。

三、Accept

指定客戶端可以接收的內容類型,內容類型的前後次序表示客戶都接收的前後次序

四、Accept-Lanuage

指定HTTP客戶端瀏覽器用來展現返回信息優先選擇的語言

五、Accept-Encoding

指定客戶端瀏覽器能夠支持的web服務器返回內容壓縮編碼類型。表示容許服務器在將輸出內容發送到客戶端之前進行壓縮,以節約帶寬。

而這裏設置的就是客戶端瀏覽器所可以支持的返回壓縮格式。

六、Accept-Charset

HTTP客戶端瀏覽器能夠接受的字符編碼集

七、Content-Type

顯示此HTTP請求提交的內容類型。通常只有post提交時才須要設置該屬性

有關Content-Type屬性值有以下兩種編碼類型:

1)「application/x-www-form-urlencoded」: 表單數據向服務器提交時所採用的編碼類型,默認的缺省值就是「application/x-www-form-urlencoded」。

     然而,在向服務器發送大量的文本、包含非ASCII字符的文本或二進制數據時這種編碼方式效率很低。

2)「multipart/form-data」: 在文件上載時,所使用的編碼類型應當是「multipart/form-data」,它既能夠發送文本數據,也支持二進制數據上載。 

當提交爲表單數據時,可使用「application/x-www-form-urlencoded」;當提交的是文件時,就須要使用「multipart/form-data」編碼類型。

八、Keep-Alive

表示是否須要持久鏈接。若是web服務器端看到這裏的值爲「Keep-Alive」,或者看到請求使用的是HTTP 1.1(HTTP 1.1默認進行持久鏈接),它就能夠利用持久鏈接的優勢

服務器響應:

Request URL: http://127.0.0.1:8888/favicon.ico

Request Method: GET

Status Code: 200 OK

Remote Address: 127.0.0.1:8888

Referrer Policy: no-referrer-when-downgrade

Content-Type: text/html;charset=utf-8

Referer: http://127.0.0.1:8888/

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36

輸出結果:

 

 

響應分爲:

第一部分:狀態行,由HTTP協議版本號, 狀態碼, 狀態消息 三部分組成。

第一行爲狀態行,(HTTP/1.1)代表HTTP版本爲1.1版本,狀態碼爲200,狀態消息爲(ok)

第二部分:消息報頭,用來講明客戶端要使用的一些附加信息

第二行和第三行爲消息報頭,
Date:生成響應的日期和時間;Content-Type:指定了MIME類型的HTML(text/html),編碼類型是UTF-8

第三部分:空行,消息報頭後面的空行是必須的
第四部分:響應正文,服務器返回給客戶端的文本信息。

空行後面的html部分爲響應正文。

4.HTTP 請求方法

根據 HTTP 標準,HTTP 請求可使用多種請求方法。

HTTP1.0 定義了三種請求方法: GET, POST 和 HEAD方法。

HTTP1.1 新增了五種請求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法。

 

HTTP 協議的 8 種請求類型介紹:

HTTP 協議中共定義了八種方法或者叫「動做」來代表對 Request-URI 指定的資源的不一樣操做方式,具體介紹以下:

OPTIONS:返回服務器針對特定資源所支持的HTTP請求方法。也能夠利用向Web服務器發送'*'的請求來測試服務器的功能性。

HEAD:向服務器索要與GET請求相一致的響應,只不過響應體將不會被返回。這一方法能夠在沒必要傳輸整個響應內容的狀況下,就能夠獲取包含在響應消息頭中的元信息。

GET:向特定的資源發出請求。

POST:向指定資源提交數據進行處理請求(例如提交表單或者上傳文件)。數據被包含在請求體中。POST請求可能會致使新的資源的建立和/或已有資源的修改。

PUT:向指定資源位置上傳其最新內容。

DELETE:請求服務器刪除 Request-URI 所標識的資源。

TRACE:回顯服務器收到的請求,主要用於測試或診斷。

CONNECT:HTTP/1.1 協議中預留給可以將鏈接改成管道方式的代理服務器。

雖然 HTTP 的請求方式有 8 種,可是咱們在實際應用中經常使用的也就是 get 和 post,其餘請求方式也均可以經過這兩種方式間接的來實現。

 

5.HTTP 響應頭信息

HTTP請求頭提供了關於請求,響應或者其餘的發送實體的信息。

Allow

服務器支持哪些請求方法(如GET、POST等)。

Content-Encoding

文檔的編碼(Encode)方法。只有在解碼以後才能夠獲得Content-Type頭指定的內容類型。利用gzip壓縮文檔可以顯著地減小HTML文檔的下載時間。Java的GZIPOutputStream能夠很方便地進行gzip壓縮,但只有Unix上的Netscape和Windows上的IE 四、IE 5才支持它。所以,Servlet應該經過查看Accept-Encoding頭(即request.getHeader("Accept-Encoding"))檢查瀏覽器是否支持gzip,爲支持gzip的瀏覽器返回經gzip壓縮的HTML頁面,爲其餘瀏覽器返回普通頁面。

Content-Length

表示內容長度。只有當瀏覽器使用持久HTTP鏈接時才須要這個數據。若是你想要利用持久鏈接的優點,能夠把輸出文檔寫入 ByteArrayOutputStream,完成後查看其大小,而後把該值放入Content-Length頭,最後經過byteArrayStream.writeTo(response.getOutputStream()發送內容。

Content-Type

表示後面的文檔屬於什麼MIME類型。Servlet默認爲text/plain,但一般須要顯式地指定爲text/html。因爲常常要設置Content-Type,所以HttpServletResponse提供了一個專用的方法setContentType。

Date

當前的GMT時間。你能夠用setDateHeader來設置這個頭以免轉換時間格式的麻煩。

Expires

應該在何時認爲文檔已通過期,從而再也不緩存它?

Last-Modified

文檔的最後改動時間。客戶能夠經過If-Modified-Since請求頭提供一個日期,該請求將被視爲一個條件GET,只有改動時間遲於指定時間的文檔纔會返回,不然返回一個304(Not Modified)狀態。Last-Modified也可用setDateHeader方法來設置。 

Location

表示客戶應當到哪裏去提取文檔。Location一般不是直接設置的,而是經過HttpServletResponse的sendRedirect方法,該方法同時設置狀態代碼爲302。

Refresh

表示瀏覽器應該在多少時間以後刷新文檔,以秒計。除了刷新當前文檔以外,你還能夠經過setHeader("Refresh", "5; URL=http://host/path")讓瀏覽器讀取指定的頁面。

注意這種功能一般是經過設置HTML頁面HEAD區的<META HTTP-EQUIV="Refresh" CONTENT="5;URL=http://host/path">實現,這是由於,自動刷新或重定向對於那些不能使用CGI或Servlet的HTML編寫者十分重要。可是,對於Servlet來講,直接設置Refresh頭更加方便。

注意Refresh的意義是"N秒以後刷新本頁面或訪問指定頁面",而不是"每隔N秒刷新本頁面或訪問指定頁面"。所以,連續刷新要求每次都發送一個Refresh頭,而發送204狀態代碼則能夠阻止瀏覽器繼續刷新,無論是使用Refresh頭仍是<META HTTP-EQUIV="Refresh" ...>。

注意Refresh頭不屬於HTTP 1.1正式規範的一部分,而是一個擴展,但Netscape和IE都支持它。

Server

服務器名字。Servlet通常不設置這個值,而是由Web服務器本身設置。

Set-Cookie

設置和頁面關聯的Cookie。Servlet不該使用response.setHeader("Set-Cookie", ...),而是應使用HttpServletResponse提供的專用方法addCookie。參見下文有關Cookie設置的討論。

WWW-Authenticate

客戶應該在Authorization頭中提供什麼類型的受權信息?在包含401(Unauthorized)狀態行的應答中這個頭是必需的。例如,response.setHeader("WWW-Authenticate", "BASIC realm=\"executives\"")。

注意Servlet通常不進行這方面的處理,而是讓Web服務器的專門機制來控制受密碼保護頁面的訪問(例如.htaccess)。

6.HTTP狀態碼

當瀏覽者訪問一個網頁時,瀏覽者的瀏覽器會向網頁所在服務器發出請求。當瀏覽器接收並顯示網頁前,此網頁所在的服務器會返回一個包含HTTP狀態碼的信息頭(server header)用以響應瀏覽器的請求。

HTTP狀態碼的英文爲HTTP Status Code。

下面是常見的HTTP狀態碼:

200 OK             //客戶端請求成功

400 Bad Request    //客戶端請求有語法錯誤,不能被服務器所理解

401 Unauthorized   //請求未經受權,這個狀態代碼必須和

//WWW-Authenticate報頭域一塊兒使用

403 Forbidden      //服務器收到請求,可是拒絕提供服務

404 Not Found       //請求資源不存在,eg:輸入了錯誤的URL

500 Internal Server Error   //服務器發生不可預期的錯誤

503 Server Unavailable   //服務器當前不能處理客戶端的請求,一段時間後可能恢復正常

7.HTTP狀態碼分類

HTTP狀態碼由三個十進制數字組成,第一個十進制數字定義了狀態碼的類型,後兩個數字沒有分類的做用。HTTP狀態碼共分爲5種類型:

1** 信息,服務器收到請求,須要請求者繼續執行操做

2** 成功,操做被成功接收並處理

3** 重定向,須要進一步的操做以完成請求

4** 客戶端錯誤,請求包含語法錯誤或沒法完成請求

5** 服務器錯誤,服務器在處理請求的過程當中發生了錯誤

更多詳細狀態碼解釋請見:點我

8.HTTP協議特性

(1)基於TCP/IP協議

http協議是基於TCP/IP協議之上的應用層協議。

 

(2)基於請求---響應模式

 

HTTP協議規定,請求從客戶端發出,最後服務器端響應 該請求並返回。換句話說,確定是先從客戶端開始創建通訊的,服務器端在沒有 接收到請求以前不會發送響應。

(3)無狀態保存

HTTP是一種不保存狀態,即無狀態(stateless)協議。HTTP協議 自身不對請求和響應之間的通訊狀態進行保存。也就是說在HTTP這個 級別,協議對於發送過的請求或響應都不作持久化處理。

使用HTTP協議,每當有新的請求發送時,就會有對應的新響應產 生。協議自己並不保留以前一切的請求或響應報文的信息。這是爲了更快地處理大量事務,確保協議的可伸縮性,而特地把HTTP協議設計成 如此簡單的。

但是,隨着Web的不斷髮展,因無狀態而致使業務處理變得棘手 的狀況增多了。好比,用戶登陸到一家購物網站,即便他跳轉到該站的 其餘頁面後,也須要能繼續保持登陸狀態。針對這個實例,網站爲了能 夠掌握是誰送出的請求,須要保存用戶的狀態。HTTP/1.1雖然是無狀態協議,但爲了實現指望的保持狀態功能, 因而引入了Cookie技術。有了Cookie再用HTTP協議通訊,就能夠管 理狀態了。有關Cookie的詳細內容後面會詳細講解。

(4)無鏈接

無鏈接的含義是限制每次鏈接只處理一個請求。服務器處理完客戶的請求,並收到客戶的應答後,即斷開鏈接。採用這種方式能夠節省傳輸時間。

二.web應用與web框架

1.web應用

應用程序有兩種模式C/SB/S

C/SClient/Server)是客戶端/服務器端程序,也就是說這類程序通常獨立運行。

B/SBrowser/Server)就是瀏覽器端/服務器端應用程序,這類應用程序通常藉助谷歌,火狐等瀏覽器來運行。

    Web應用程序通常是B/S模式。Web應用程序首先是應用程序,和用什麼程序語言(如:javapython等)編寫出來的程序沒有什麼本質上的不一樣。在網絡編程的意義下,瀏覽器是一個socket客戶端,服務器是一個socket服務端。

基於socket實現一個最簡單的web應用程序

#!/usr/bin/env python

# -*- coding:utf-8 -*-

# by hsz

import socket

# 建立socket對象

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

 

# 綁定IP和端口

sock.bind(("127.0.0.1", 8888))

 

# 監聽

sock.listen(5)

 

while True:

    conn, addr = sock.accept()  # 等待鏈接

 

    data = conn.recv(1024)  # 接收數據

    print("請求信息====>  %s" % data)

 

    # 發送數據

    conn.send("HTTP/1.1 200 OK\r\nContent-Type: text/html;charset=utf-8\r\n\r\n".encode('utf-8'))

    conn.send("<h2>hello http</h2>".encode("utf-8"))

conn.close()

 

 

 

2.wsgiref模塊

最簡單的Web應用就是先把HTML用文件保存好,用一個現成的HTTP服務器軟件,接收用戶請求,從文件中讀取HTML,返回。

若是要動態生成HTML,就須要把上述步驟本身來實現。不過,接受HTTP請求、解析HTTP請求、發送HTTP響應都是苦力活,若是咱們本身來寫這些底層代碼,還沒開始寫動態HTML呢,就得花個把月去讀HTTP規範。

正確的作法是底層代碼由專門的服務器軟件實現,咱們用Python專一於生成HTML文檔。由於咱們不但願接觸到TCP鏈接、HTTP原始請求和響應格式,因此,須要一個統一的接口協議來實現這樣的服務器軟件,讓咱們專心用Python編寫Web業務。這個接口就是WSGIWeb Server Gateway Interface。而wsgiref模塊就是python基於wsgi協議開發的服務模塊。

例:

from wsgiref.simple_server import make_server

 

 

def application(environ, start_response):

    start_response('200 OK', [('Content-Type', 'text/html')])

    return [b'<h1>Hello, web!</h1>']

 

 

if __name__ == '__main__':

    httpd = make_server('', 8080, application)

    print('Serving HTTP on port 8080...')

    # 開始監聽HTTP請求:

httpd.serve_forever()

 

訪問:http://127.0.0.1:8080/

便可獲得標題:Hello, web!

 

3.Web框架

Web框架(Web framework)是一種開發框架,用來支持動態網站、網絡應用和網絡服務的開發。這大多數的web框架提供了一套開發和部署網站的方式,也爲web行爲提供了一套通用的方法。web框架已經實現了不少功能,開發人員使用框架提供的方法而且完成本身的業務邏輯,就能快速開發web應用了。

瀏覽器和服務器之間是基於HTTP協議進行通訊的。也能夠說web框架就是在以上十幾行代碼基礎張擴展出來的,有不少簡單方便使用的方法,大大提升了開發的效率。

4.一個Web框架demo

(1)啓動文件manage.py

#!/usr/bin/env python

# -*- coding:utf-8 -*-

# by hsz

from wsgiref.simple_server import make_server

from urls import *

 

 

def application(environ, start_response):

    start_response('200 OK', [('Content-Type', 'text/html;charset=utf-8')])

    path = environ.get("PATH_INFO")

    func = None

    for item in urlpatterns:

        if path == item[0]:

            func = item[1]

            break

    if func:

        ret = func(environ)

    else:

        ret = not_found(environ)

 

    return [ret]

 

 

if __name__ == '__main__':

    # 請求端口

    httpd = make_server('', 8080, application)

    print('Serving HTTP on port 8080...')

    # 開始監聽HTTP請求:

httpd.serve_forever()

 

(2)urls.py

#!/usr/bin/env python

# -*- coding:utf-8 -*-

# by hsz

from views import *

 

urlpatterns = [

    ("/login/", login),

]

 

(3)views.py

#!/usr/bin/env python

# -*- coding:utf-8 -*-

# by hsz

def login(environ):

    with open("templates/login.html", "rb") as f:

        data = f.read()

        return data

 

 

def not_found(environ):

    ret = b'<h1>404 not found.!!!</h1>'

return ret

 

(4)templates模板目錄(該目錄下建立login.html網頁)

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <title></title>

</head>

<body>

<form action="http://127.0.0.1:8080/login/" method="post">

    <p>用戶名:<input type="text" name="user"></p>

    <p>密碼:<input type="password" name="pwd"></p>

    <input type="submit">

</form>

</body>

</html>

相關文章
相關標籤/搜索