zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

request.ex (2224B)


      1 defmodule Mint.HTTP1.Request do
      2   @moduledoc false
      3 
      4   import Mint.HTTP1.Parse
      5 
      6   def encode(method, target, headers, body) do
      7     body = [
      8       encode_request_line(method, target),
      9       encode_headers(headers),
     10       "\r\n",
     11       encode_body(body)
     12     ]
     13 
     14     {:ok, body}
     15   catch
     16     {:mint, reason} -> {:error, reason}
     17   end
     18 
     19   defp encode_request_line(method, target) do
     20     validate_target!(target)
     21     [method, ?\s, target, " HTTP/1.1\r\n"]
     22   end
     23 
     24   defp encode_headers(headers) do
     25     Enum.reduce(headers, "", fn {name, value}, acc ->
     26       validate_header_name!(name)
     27       validate_header_value!(name, value)
     28       [acc, name, ": ", value, "\r\n"]
     29     end)
     30   end
     31 
     32   defp encode_body(nil), do: ""
     33   defp encode_body(:stream), do: ""
     34   defp encode_body(body), do: body
     35 
     36   def encode_chunk(:eof) do
     37     "0\r\n\r\n"
     38   end
     39 
     40   def encode_chunk({:eof, trailing_headers}) do
     41     ["0\r\n", encode_headers(trailing_headers), "\r\n"]
     42   end
     43 
     44   def encode_chunk(chunk) do
     45     length = IO.iodata_length(chunk)
     46     [Integer.to_string(length, 16), "\r\n", chunk, "\r\n"]
     47   end
     48 
     49   # Percent-encoding is not case sensitive so we have to account for lowercase and uppercase.
     50   @hex_characters '0123456789abcdefABCDEF'
     51 
     52   defp validate_target!(target), do: validate_target!(target, target)
     53 
     54   defp validate_target!(<<?%, char1, char2, rest::binary>>, original_target)
     55        when char1 in @hex_characters and char2 in @hex_characters do
     56     validate_target!(rest, original_target)
     57   end
     58 
     59   defp validate_target!(<<char, rest::binary>>, original_target) do
     60     if URI.char_unescaped?(char) do
     61       validate_target!(rest, original_target)
     62     else
     63       throw({:mint, {:invalid_request_target, original_target}})
     64     end
     65   end
     66 
     67   defp validate_target!(<<>>, _original_target) do
     68     :ok
     69   end
     70 
     71   defp validate_header_name!(name) do
     72     _ =
     73       for <<char <- name>> do
     74         unless is_tchar(char) do
     75           throw({:mint, {:invalid_header_name, name}})
     76         end
     77       end
     78 
     79     :ok
     80   end
     81 
     82   defp validate_header_value!(name, value) do
     83     _ =
     84       for <<char <- value>> do
     85         unless is_vchar(char) or char in '\s\t' do
     86           throw({:mint, {:invalid_header_value, name, value}})
     87         end
     88       end
     89 
     90     :ok
     91   end
     92 end