HTTP/1.0 200 Found
Cache-Control: no-cache
Connection: close
Content-Type: text/plain
# Discourse CDN, all crawling is allowed (cdn contains images and text files)
User-Agent: *
Allow: /
This means that when people hit: https://cdn.discourse.org/robots.txt well they get the robots file.
This hack works OK, except that now we are logging a bunch of 503 statuses in the logs which in reality are 200s, this in turn makes log analysis a bit annoying.
Is there another hack we can use that allows us to serve a single static file from a backend and retain status 200 in the logs?
Anyone have a good example of how to serve a single static file using lua?
Looks a bit less hacky than above, would like to create a landing page for an ssl verify required scenario, vs. just present a request for cert.
There is a hello world example here, but it doesn’t have much:
I got a LUA response working based on the rabbit trail @mattpark started me down. I am using this with HAproxy running on pfSense.
I have several responses in a single lua file and just call them by function name (service at the bottom)
Here is an example from my lua file, just replace the response data with the contents of your robots.txt, indicating new lines by a \n . If you want this to be HTML (or any other file type) just change the Content-Type header as needed.
http_resp = function(applet)
local response = "Your Content goes here.\n use backslash+n to generate a new line"
applet:add_header("Content-Length", string.len(response))
applet:add_header("Content-Type", "text/plain")
applet:set_status(200)
applet:start_response()
applet:send(response)
end
core.register_service("http_resp", "http", http_resp)
@sam, I’m sure you found an acceptable solution a long time ago, but I found this thread today and am not using this solution to disallow robots indexing on all of my backends at once with this frontend LUA config.
My specific robots.txt response uses this as the ACL to match to call the function.
Name Expression Value Actions
robots Path ends with: robots.txt
Hey there,
I came up with the following solution for serving files just like a web-server would do with the help of LUA. The following frontend-config sets the HTTP-header X-LUA-LOADFILE-DOCROOT with a local directory path which serves as the document-root. Furthermore, it defines a lua-service called load-file. See:
As you can see I load a lua-file called load-file.lua. The contents of that file are as follows:
core.register_service("load-file", "http", function(applet)
local docroot
local location
local file
local retval
local response
local extension
if(applet.path == nil or applet.headers["x-lua-loadfile-docroot"] == nil or applet.headers["x-lua-loadfile-docroot"][0] == "") then
retval = 500
response = "Internal Server Error"
else
docroot = applet.headers["x-lua-loadfile-docroot"][0]
location = applet.path
if(location == "" or location == "/") then
location = "/index.html"
end
file = io.open(docroot .. location, "r")
if(file == nil) then
retval = 404
response = "File Not Found"
else
retval = 200
response = file:read("*all")
file:close()
end
end
extension = string.match(location, ".(%w+)$")
if extension == "css" then applet:add_header("content-type", "text/css")
elseif extension == "gif" then applet:add_header("content-type", "image/gif")
elseif extension == "htm" then applet:add_header("content-type", "text/html")
elseif extension == "html" then applet:add_header("content-type", "text/html")
elseif extension == "ico" then applet:add_header("content-type", "image/x-icon")
elseif extension == "jpg" then applet:add_header("content-type", "image/jpeg")
elseif extension == "jpeg" then applet:add_header("content-type", "image/jpeg")
elseif extension == "js" then applet:add_header("content-type", "application/javascript; charset=UTF-8")
elseif extension == "json" then applet:add_header("content-type", "application/json")
elseif extension == "mpeg" then applet:add_header("content-type", "video/mpeg")
elseif extension == "png" then applet:add_header("content-type", "image/png")
elseif extension == "txt" then applet:add_header("content-type", "text/plain")
elseif extension == "xml" then applet:add_header("content-type", "application/xml")
elseif extension == "zip" then applet:add_header("content-type", "application/zip")
end
applet:set_status(retval)
if(response ~= nil and response ~= "") then
applet:add_header("content-length", string.len(response))
end
applet:start_response()
applet:send(response)
end)
Basically, this code reads files from a specified document-root location in the filesystem based on the query string and generates appropriate HTTP-responses just as a normal webserver would do. That is why the script needs a document-root do be configured via the HTTP-header X-LUA-LOADFILE-DOCROOT . Furthermore, the code also does some very basic mimetype handling - extend the list according your needs. I hope someone finds this useful.
Thanks for the advice - I was feeling a little bit bad about doing IO like that and was thinking that I should be reading it in at start and caching it, but since http-request returndoes exactly that we’re now trying out HAProxy 2.3.