|
1 | | -local rawget, rawset, setmetatable = |
2 | | - rawget, rawset, setmetatable |
3 | | - |
4 | | -local str_find, str_lower, str_sub = |
5 | | - string.find, string.lower, string.sub |
| 1 | +local rawget, rawset, setmetatable = |
| 2 | + rawget, rawset, setmetatable |
6 | 3 |
|
| 4 | +local str_lower = string.lower |
7 | 5 |
|
8 | 6 | local _M = { |
9 | 7 | _VERSION = '0.10', |
10 | 8 | } |
11 | 9 |
|
12 | 10 |
|
13 | | -local function hyphenate(k) |
14 | | - local k_hyphened = "" |
15 | | - local match = false |
16 | | - local prev_pos = 0 |
17 | | - |
18 | | - repeat |
19 | | - local pos = str_find(k, "_", prev_pos, true) |
20 | | - if pos then |
21 | | - match = true |
22 | | - k_hyphened = k_hyphened .. str_sub(k, prev_pos, pos - 1) .. "-" |
23 | | - elseif match == false then |
24 | | - -- Didn't find an underscore and first check |
25 | | - return k |
26 | | - else |
27 | | - -- No more underscores, append the rest of the key |
28 | | - k_hyphened = k_hyphened .. str_sub(k, prev_pos) |
29 | | - break |
30 | | - end |
31 | | - prev_pos = pos + 1 |
32 | | - until not pos |
33 | | - |
34 | | - return k_hyphened |
35 | | -end |
36 | | - |
37 | | - |
38 | 11 | -- Returns an empty headers table with internalised case normalisation. |
39 | | --- Supports the same cases as in ngx_lua: |
40 | | --- |
41 | | --- headers.content_length |
42 | | --- headers["content-length"] |
43 | | --- headers["Content-Length"] |
44 | | -function _M.new(self) |
| 12 | +function _M.new() |
45 | 13 | local mt = { |
46 | 14 | normalised = {}, |
47 | 15 | } |
48 | 16 |
|
49 | 17 | mt.__index = function(t, k) |
50 | | - local k_hyphened = hyphenate(k) |
51 | | - local k_normalised = str_lower(k_hyphened) |
52 | | - return rawget(t, mt.normalised[k_normalised]) |
| 18 | + return rawget(t, mt.normalised[str_lower(k)]) |
53 | 19 | end |
54 | 20 |
|
55 | | - -- First check the normalised table. If there's no match (first time) add an entry for |
56 | | - -- our current case in the normalised table. This is to preserve the human (prettier) case |
57 | | - -- instead of outputting lowercased header names. |
58 | | - -- |
59 | | - -- If there's a match, we're being updated, just with a different case for the key. We use |
60 | | - -- the normalised table to give us the original key, and perorm a rawset(). |
61 | 21 | mt.__newindex = function(t, k, v) |
62 | | - -- we support underscore syntax, so always hyphenate. |
63 | | - local k_hyphened = hyphenate(k) |
64 | | - |
65 | | - -- lowercase hyphenated is "normalised" |
66 | | - local k_normalised = str_lower(k_hyphened) |
| 22 | + local k_normalised = str_lower(k) |
67 | 23 |
|
| 24 | + -- First time seeing this header field? |
68 | 25 | if not mt.normalised[k_normalised] then |
69 | | - mt.normalised[k_normalised] = k_hyphened |
70 | | - rawset(t, k_hyphened, v) |
| 26 | + -- Create a lowercased entry in the metatable proxy, with the value |
| 27 | + -- of the given field case |
| 28 | + mt.normalised[k_normalised] = k |
| 29 | + |
| 30 | + -- Set the header using the given field case |
| 31 | + rawset(t, k, v) |
71 | 32 | else |
| 33 | + -- We're being updated just with a different field case. Use the |
| 34 | + -- normalised metatable proxy to give us the original key case, and |
| 35 | + -- perorm a rawset() to update the value. |
72 | 36 | rawset(t, mt.normalised[k_normalised], v) |
73 | 37 | end |
74 | 38 | end |
|
0 commit comments