淺談HTTP之URL

背景介紹

從畢業到工做都一年多了,在這一年多的時間裏,我發現有的後臺程序員連 URL 的查詢參數都不知道,再加上最近使用 node 和 python 鏈接加密的 mongodb 時也遇到了點問題,就決定對我所知道的 URL 方面知識作一個總結。javascript

何爲URL

名詞解釋

URL 是 Uniform Resource Location 的縮寫,譯爲「統一資源定位符」。通俗地說, URL 是 Internet 上用來描述信息資源的字符串,主要用在各類 www 客戶程序和服務器程序上。採用URL能夠用一種統一的格式來描述各類信息資源,包括文件、服務器的地址和目錄等。css

順便也提一下 URI 吧:html

Web上可用的每種資源 - HTML文檔、圖像、視頻片斷、程序等 - 由一個經過通 用資源標誌符(Universal Resource Identifier, 簡稱"URI")進行定位。前端

URI通常由三部分組成:java

  • 訪問資源的命名機制。
  • 存放資源的主機名。
  • 資源自身的名稱,由路徑表示。

URL 是 URI 的子集,可是平時的開發中咱們只須要了解 URL 就能夠了。node

URL格式

http://test.com:8080/example/index.html爲例進行說明。python

URL的格式由下列三部分組成:linux

  • 第一部分是協議(或稱爲服務方式),本例中爲HTTP 協議
  • 第二部分是存有該資源的主機IP地址或域名(有時也包括端口號),本例中爲 test.com:8080。平時看到的都是域名,以後客戶端會經過DNS(域名系統) 查詢域名對應的 IP,而後根據IP和端口號進行服務器的鏈接。稍後會對此進行詳細說明。
  • 第三部分是主機資源的具體地址,如目錄和文件名等,本例中爲 /example/index.html

URL 的語法

通用語法

<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>nginx

  • scheme: 協議,常見的有 http(80),https(443),mailto,ftp(21),rtsp,rtspu,file。
  • user:用戶名。
  • password: 密碼。
  • host:主機。
  • port: 端口。
  • params: 參數。一般爲 key=value
  • query:查詢參數或查詢字符串。
  • frag: 片斷(在瀏覽器中會被解析爲 window.location.hash)。

這只是通用語法,大多數的 URL 都只遵循了一部分而已,並非每種URL都會有上面的全部信息。git

從上面的語法咱們能夠看出至少 :/@;?# 都是敏感字符,因此在其餘參數中不能包含這些字符,若是含有敏感字符或者特殊字符,就須要使用對應的轉義字符,不然可能會發生不可預料的結果。 在開發過程當中,容易在查詢參數中含有 敏感字符,因此查詢字符串的值通常都須要使用 encodeURIComponent進行編碼。

http(s)中的語法

http://test.com:8080/user/index.html?id=1&nickName=test#/list

在瀏覽器中被解析後的格式爲:

{
    protocol: 'http:', // 協議
    host: 'test.com:8080', // 主機名或域名,帶端口號
    hostname: 'test.com', // 主機名或域名,不帶端口號
    port: '', // 端口號,http默認80,https默認443
    path: '/user/index.html', // 路徑
    query: '?id=1&nickName=test'// 查詢字符串
    hash: '#list', //片斷或者哈希,
}
複製代碼

注意: #後面的東西都不會從客戶端傳到服務器。

在地址欄中改變 # 後的字符串時,頁面並不會刷新,可是會出發 hashchange 事件,不少前端路由的 hash 模式就是根據這種特性實現的。而改變出了frag(hash)以外的東西都會致使瀏覽器刷新,由於此時至關於向服務器發出了一個新的請求。

ftp中的語法

文件傳輸協議,能夠用來從服務器下載或上傳文件。

基本格式:

ftp://<user>:<password>@<host>:<port>/<path>;<params>

示例:

ftp://ftpuser:123456.com@test.com:21/path/example

file中的語法

該協議常見於本地文件於瀏覽器中打開的場景,也多是網絡文件系統或者其餘一些文件共享系統。這個我就不細說了,感受沒啥可說的。

mongodb協議

常見於後臺程序鏈接 mongodb 數據庫。雖然咱們常見的包都是用對象格式來鏈接數據庫的,可是最後都會被轉化爲字符串形式的。

基本格式:

mongodb://<user>:<password>@<host>:<port>/<path>?<query>

示例:

mongodb://test:123456@127.0.0.1:27017/novel?authSource=admin 該字符串表示以 mongodb 協議,用戶名爲test,密碼爲123456,數據庫dbName爲novel,驗證的數據庫爲admin,鏈接至127.0.0.1主機的27017端口。

注意:如mongodb服務器沒有開啓加密,須要去掉查詢參數,不然會鏈接失敗。若開啓了加密,authSource的值必須和前方的user和password相對應。,不然用戶驗證頁沒法鏈接。 我用的thinkjs,一開始沒有配置 authSource,給我報的錯誤是鏈接超時,當時還納悶遠程的服務器再慢也不至於吧???後來調整了超時時間,發現仍是超時,並且一直在嘗試從新鏈接,就想到了多是驗證失敗了,這個糾結了很多時間。

在瀏覽器中輸入URL後,執行的所有過程

整個流程以下:

  1. 域名解析;
  2. 發起TCP的3次握手;
  3. 創建TCP鏈接後發起http請求;
  4. 服務器響應htp請求;
  5. 瀏覽器解析htm代碼,並請求html代碼中的資源(如js、css、圖片等);
  6. 斷開TCP鏈接;
  7. 瀏覽器對頁面進行渲染呈現給用戶。

其實,域名解析這個過程要是細說的話仍是有點複雜的,總之有時候也是蠻耗時的,畢竟從 解析 這個用詞咱們就能看出它必定是須要時間的?經過DNS會將域名解析爲 IP,以後會根據 IP 和 端口鏈接服務器。

若是咱們直接用IP訪問服務器,就能夠節省一部分時間,但仍是不建議你們這麼作,由於若是更換了服務器的話,域名能夠解析到另外一個IP,能夠在瀏覽器端保留相應的數據,而IP就不行了。還有就是,域名的可訪問性和可讀性可比IP強多了。

動態服務器和靜態服務器

上面的大部分都只適用於靜態服務器,若是是動態服務器的話,它會有本身的一套解析規則,可是大體上也是相同的,最大的區別可能仍是動態服務器的動態路由吧(前端路由如今也支持動態路由了)。

下面主要就說一下動態服務器相對於靜態服務器的特殊點:

動態路由

好比定義一個獲取某我的的信息的接口,它的路徑爲:{ path: '/user/:id' }

當訪問 /user/1?name=test時,該接口將被框架解析爲:

{
    params: {
        id: 1,
    },
    query: {
        name: 'test',
    }
}
複製代碼

若是是靜態路由的話,只能使用 /user?id=1&name=test這種方式來傳遞參數了,從這能夠看出動態路由在必定程度上仍是比靜態路由有一點優點的;並且動態路由看上去更優雅。

可是若是後臺對路由的定義很差,前端傳過去的參數爲空的話,動態路由就會變成 /user/,訪問到的接口就不是 /user/:id這個路由,而是 /user/這個接口了,後臺差找不到該路由,直接就返回 404 或者自定義的錯誤了。

路由重寫

我接觸過的後臺框架有 ThinkPHP 和 thinkjs, 這兩個仍是比較類似的,它們都有一個特性就是可以進行路由重寫,好比在定義好的路由以後加上後綴,若是設置 ext: '.html',那麼訪問 /user/1.html時將被解析爲 /user/:id,在那些先後端還未分離的公司,這個應該是主要的頁面輸出方式了(記得不知道從哪看到的這樣好像有利於SEO優化?)。

因此之後在看到 http://test.com/user/1.html 這樣的 URL的時候,就不能再單純的認爲它必定指向服務器的某個靜態文件,它如今也多是通過模板渲染以後的一個響應。

說了點動態服務器的,那就再說一點靜態服務器的吧,由於我遇到的一個後臺,在前端上傳文件後,直接把文件存儲到linux系統的根目錄,而後在域名後面把文件的路徑拼上去,還納悶怎麼就是訪問不到呢?

甘拜下風

web服務器的根目錄

經常使用的靜態服務器是 nginx,設置一下靜態文件的壓縮啦,緩存啦,代理啦,識別設備進行跳轉,圖片裁剪之類的,都是so easy,簡直就是咱們大前端的標配嘛。

話雖然這麼說,如今的公司仍是把個人前端文件放在tomcat容器下,並無給我一個專屬的 nginx 服務器,o(╥﹏╥)o。每次改完文件我得先打包成壓縮包,發給後臺,他放到 tomcat 容器下,而後再上傳至服務器,重啓容器,最後緩存沒控制好,壓縮也沒搞。重啓以後還得懷疑一下個人文件是否是發錯了,這文件怎麼沒更新???其實用 nginx,再搭配 git 的 hooks,幾個命令行的事而已嘛,扯遠了,仍是說說 web服務器的根目錄吧。

流行一點的web服務器主要是 nginx, apache,tomcat,後兩個主要仍是用於搭配後臺使用,不直接向外暴露接口的。這些靜態服務器都會有一個配置用於設置 web 服務器的根目錄,那麼這個根目錄的做用是什麼呢?就是控制客戶端能訪問到的頂級目錄。 好比根目錄是 www,是不能訪問 www 目錄之外的其餘文件的,只能訪問 www 的子目錄的各文件。

參考連接

相關文章
相關標籤/搜索