[elixir! #0064] 在2020年繼續使用 http 1.0 協議會發生什麼

HTTP 是目前互聯網上最經常使用的協議,不單單應用於訪問網頁,如今一些內部服務也開始使用 HTTP,例如 gPRC 等等。 app

其實 HTTP 協議的內部結構很是簡單,我嘗試寫了一個最簡單的 HTTP 客戶端,功能只有:dom

  1. 從 DNS 獲取到域名對應的 ip
  2. 向 ip 發送一個 tcp 消息,內容是一個 HTTP GET 請求的字符串
  3. 返回收到的回覆

由於沒有解析 header 的功能,因此只能根據時間來判斷回覆是否已經結束 :P。socket

defmodule M7 do
  @data """
  GET / HTTP/1.0\r\n
  """

  def test(domain) do
    ip = getip(domain)
    {:ok, socket} = :gen_tcp.connect(ip, 80, [:binary, {:active, true}])

    :gen_tcp.send(socket, @data)

    loop_receive()
  end

  def getip(url) do
    {:ok, {:hostent, _, _, :inet, _, ips}} =
      String.to_charlist(url)
      |> :inet_res.gethostbyname()

    hd(ips)
  end

  defp loop_receive() do
    Stream.repeatedly(fn ->
      receive do
        {:tcp, _port, data} ->
          {:ok, data}
      after
        1000 ->
          {:error, :timeout}
      end
    end)
    |> Enum.reduce_while([], fn
      {:ok, data}, acc ->
        {:cont, [data | acc]}

      {:error, _}, acc ->
        {:halt, Enum.reverse(acc)}
    end)
    |> IO.iodata_to_binary()
  end
end

嘗試幾個著名網站,發現只有 google 會正常返回網頁的內容。apple 會按 HTTP/1.0 協議返回 400。其它的網站不是不返回任何東西,就是以 HTTP/1.1 返回一個錯誤信息。tcp

我以爲多是一些網站不支持 HTTP/1.0,也多是它們發現個人請求裏沒有附帶一些必要的 Header 因此拒絕服務。oop

以爲有趣就點個贊?吧~ 週一到週五天天更新。網站

相關文章
相關標籤/搜索