summaryrefslogtreecommitdiffstatshomepage
path: root/plugins/weblit/auto-headers.lua
blob: 44ad65779e93950d9ea8d090893146030dd864f7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
--[[

Response automatic values:
 - Auto Server header
 - Auto Date Header
 - code defaults to 404 with body "Not Found\n"
 - if there is a string body add Content-Length and ETag if missing
 - if string body and no Content-Type, use text/plain for valid utf-8, application/octet-stream otherwise
 - Auto add "; charset=utf-8" to Content-Type when body is known to be valid utf-8
 - Auto 304 responses for if-none-match requests
 - Auto strip body with HEAD requests
 - Auto chunked encoding if body with unknown length
 - if Connection header set and not keep-alive, set res.keepAlive to false
 - Add Connection Keep-Alive/Close if not found based on res.keepAlive

--TODO: utf8 scanning

]]

--local digest = require('openssl').digest.digest
local date = require('os').date

return function (req, res, go)
  local isHead = false
  if req.method == "HEAD" then
    req.method = "GET"
    isHead = true
  end

  local requested = req.headers["if-none-match"]

  go()

  -- We could use the fancy metatable, but this is much faster
  local lowerHeaders = {}
  local headers = res.headers
  for i = 1, #headers do
    local key, value = unpack(headers[i])
    lowerHeaders[key:lower()] = value
  end


  if not lowerHeaders.server then
    headers[#headers + 1] = {"Server", serverName}
  end
  if not lowerHeaders.date then
    headers[#headers + 1] = {"Date", date("!%a, %d %b %Y %H:%M:%S GMT")}
  end

  if not lowerHeaders.connection then
    if req.keepAlive then
      lowerHeaders.connection = "Keep-Alive"
      headers[#headers + 1] = {"Connection", "Keep-Alive"}
    else
      headers[#headers + 1] = {"Connection", "Close"}
    end
  end
  res.keepAlive = lowerHeaders.connection and lowerHeaders.connection:lower() == "keep-alive"

  local body = res.body
  if body then
    local needLength = not lowerHeaders["content-length"] and not lowerHeaders["transfer-encoding"]
    if type(body) == "string" then
      if needLength then
        headers[#headers + 1] = {"Content-Length", #body}
      end
  --    if not lowerHeaders.etag then
    --    local etag = '"' .. digest("sha1", body) .. '"'
      --  lowerHeaders.etag = etag
        --headers[#headers + 1] = {"ETag", etag}
     -- end
    else
      if needLength then
        headers[#headers + 1] = {"Transfer-Encoding", "chunked"}
      end
    end
    if not lowerHeaders["content-type"] then
      headers[#headers + 1] = {"Content-Type", "text/plain"}
    end
  end

  local etag = lowerHeaders.etag
  if requested and res.code >= 200 and res.code < 300 and requested == etag then
    res.code = 304
    body = nil
  end

  if isHead then body = nil end
  res.body = body
end