目錄
認識“狀態碼”(status code)
200 OK
404 Not Found
403 Forbidden
405 Method Not Allowed
500 Internal Server Error
504 Gateway Timeout
302 Move temporarily
301 Moved Permanently
418 I am a teaport
狀態碼小結:
認識響應“報頭”(header)
Content - Type
構造 HTTP 請求
通過第三方工具進行構造
通過代碼來構造 HTTP 請求
完!
認識“狀態碼”(status code)
狀態碼是表示一個頁面的結果。(是訪問成功,還是失敗,話是其他的一些情況...)
HTTP 中的狀態碼都是約定好的:
上面的狀態碼并不需要全部都記住,只需要直到幾個常見的狀態碼即可~~
200 OK
這是一個最常見的狀態碼, 表示訪問成功
404 Not Found
表示沒有找到資源。
瀏覽器輸入一個 URL,目的就是為了訪問對方服務器上的一個資源。如果這個 URL 標識的資源不存在,那么就會出現 404。例如,在瀏覽器中輸入 www.bilibli.com/index.html,此時就在嘗試訪問 嗶哩嗶哩上的 /index.html 這個資源。
如果輸入正確,就可以正確訪問到,但是如果輸入錯誤,比如 www.bilibili.com/index333.html,就會看到 404 這樣的響應。(不過 bilibili 比較有特點,他特意為 404 做了一個比較符合宅男動漫的頁面~~)
403 Forbidden
表示訪問被拒絕。有的頁面通常需要用戶具有一定的權限(比如登陸后才能進行訪問)如果用戶沒有登錄直接訪問,就容易看到 403。
例如:我們在碼云上查看一個其他人的私人倉庫,就會出現 403,參考鏈接:https://gitee.com/HGtz2222/blog_python
405 Method Not Allowed
前面我們學習了 HTTP 中所支持的方法,有 GET,POST,PUT,DELETE 等等。
但是對方的服務器不一定支持所有的方法,比如:服務器只支持 GET 請求,但是我們發送了一個 POST,就會出現 405 Method Not Allowed。
500 Internal Server Error
服務器內部出現錯誤,一般是服務器的代碼執行過程中,遇到了一些特殊的情況(服務器崩潰)會產生這個狀態碼~~
504 Gateway Timeout
當服務器負載比較大的時候,服務器處理單條請求的時間消耗的時間就會很長,就可能出現訪問服務器超時。這種情況可能是服務器掛了,也可能是網絡掛了~~
302 Move temporarily
臨時重定向
理解“重定向”
就相當于手機號碼中的“呼叫轉移”功能。
比如我們本來的手機號是 123-4567-7899,后來換了一個新的號碼是 999-4567-7891,此時難道是一個一個朋友告訴我們的新號碼碼??
我們可以去辦理一個呼叫轉移業務,其他人撥打 123-4567-7899 的時候,就會自動轉移到999-4567-7891 上
我們在登錄頁面經常會見到 302,用戶實現登陸成功后自動跳轉到主頁。
響應報文中的 header 部分會包含一個 Location 字段,表示要跳轉到那個頁面~~
我們以碼云的登錄為例:登陸后的抓包結果:
可以看到 header 中的 Location:https://gitee.com/,接下來瀏覽器就會自動發送 GET?
請求,獲取 https://gitee.com/?
301 Moved Permanently
永久重定向,當瀏覽器收到這種響應時候,后續的請求都會被自動改成新的地址,不必多一次跳轉了。(可以影響到瀏覽器的緩存)
在上面 301 和 302 這種重定向報文的響應中,會有一個特殊的 header 叫做 Location,描述了要重定向的位置是在哪里~~
418 I am a teaport
一個特殊的狀態碼,沒有實際的含義,I am a teaport 我是個茶壺(我是個杯具~~)?
設計 HTTP 協議的大佬開玩笑 == 》 “彩蛋~”
狀態碼小結:
認識響應“報頭”(header)
響應報頭的基本格式和請求報頭的格式基本一致
類似 Content - Type,Content - Length 等屬性的含義也和請求中的含義一致~~
Content - Type
響應中的 Content - Type 常見取值有以下幾種:
text/html :body 數據格式是 HTML
text/css: body 數據格式是 CSS
application/javascript: body 數據格式是 Javascript
application/json: body 數據格式是 JSON
構造 HTTP 請求
通過第三方工具進行構造
使用 postman 就可以構造 HTTP 請求~
每個標簽頁,就是一個構造 HTTP 請求的配置頁面了,點擊 Send 發送按鈕,就能發送請求到目標服務器了~~
還有一個很牛逼的點是:postman 是一個有對象的軟件 == > postwoman~~
通過代碼來構造 HTTP 請求
任何一種編程語言,只要能夠操作網絡,都可以構造 HTTP 請求!!
所謂”發送 HTTP 請求“,本質上就是按照 HTTP 的格式往 TCP Socket 中寫入一個字符串。
所謂”接受 HTTP 響應“,本質上就是從 TCP Socket 中讀取一個字符串,再按照 HTTP 的格式來解析。
我們就可以基于 Socket 的知識,構造出一個簡單的 HTTP 客戶端程序,用來發送各種類型的 HTTP 請求。
public class HttpClient {private Socket socket;private String ip;private int port;public HttpClient(String ip, int port) throws IOException {this.ip = ip;this.port = port;socket = new Socket(ip, port);}public String get(String url) throws IOException {StringBuilder request = new StringBuilder();// 構造首行request.append("GET " + url + " HTTP/1.1\n");// 構造 headerrequest.append("Host: " + ip + ":" + port + "\n");// 構造空行request.append("\n");// 發送數據OutputStream outputStream = socket.getOutputStream();outputStream.write(request.toString().getBytes());// 讀取響應數據InputStream inputStream = socket.getInputStream();byte[] buffer = new byte[1024 * 1024];int n = inputStream.read(buffer);return new String(buffer, 0, n, "utf-8");}public String post(String url, String body) throws IOException {StringBuilder request = new StringBuilder();// 構造首行request.append("POST " + url + " HTTP/1.1\n");// 構造 headerrequest.append("Host: " + ip + ":" + port + "\n");request.append("Content-Length: " + body.getBytes().length + "\n");request.append("Content-Type: text/plain\n");// 構造空行request.append("\n");// 構造 bodyrequest.append(body);// 發送數據OutputStream outputStream = socket.getOutputStream();outputStream.write(request.toString().getBytes());// 讀取響應數據InputStream inputStream = socket.getInputStream();byte[] buffer = new byte[1024 * 1024];int n = inputStream.read(buffer);return new String(buffer, 0, n, "utf-8");}public static void main(String[] args) throws IOException {HttpClient httpClient = new HttpClient("www.bilibili.com",80);String resp = httpClient.get("/index.html");System.out.println(resp);String postResp = httpClient.post("/index.html","this is a body");System.out.println(postResp);}
}