Skip to content

Commit ec2de6a

Browse files
authored
Merge pull request #34 from e404/fixes
Fixes
2 parents b81c1f1 + e3796c0 commit ec2de6a

File tree

2 files changed

+42
-83
lines changed

2 files changed

+42
-83
lines changed

README.md

Lines changed: 12 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,12 @@ When using nginx, there are many **legitimate reasons** to support `.htaccess` f
2525
* **Justified.** Apache performs multiple file reads anyway, so .htaccess for nginx cannot make it worse than Apache, right? In fact, with our built-in micro caching mechanism both, CPU and I/O load are reduced drastically compared to Apache's implementation.
2626
* **For webhosters.** Today, webhosters still need to provide an interface for their customers to change certain aspects of their webserver's behaviour. The decades long and proven `.htaccess` file does just that.
2727

28-
2928
## Performance
3029

3130
**.htaccess for nginx is incredibly lightweight and fast!** It is written from the ground up with performance optimizations in mind. Even with low-end hardware it adds less than 1 millisecond to your response time, despite supporting quite complex rewrite structures with server variables.
3231

3332
Physical memory usage of this plugin is insanely low, under 10 KB for each nginx worker process, and it doesn't increase with more requests.
3433

35-
3634
## Requirements
3735

3836
* Debian or Fedora environment
@@ -44,11 +42,11 @@ Physical memory usage of this plugin is insanely low, under 10 KB for each nginx
4442

4543
## Installation
4644

47-
1. Install nginx with the [Lua module](https://github.com/openresty/lua-nginx-module) `libnginx-mod-http-lua` and the `luajit` package.
48-
1. Debian: `apt-get install nginx libnginx-mod-http-lua luajit`
49-
2. Fedora: `yum install nginx libnginx-mod-http-lua luajit`
50-
51-
1. Verify that the Lua module is properly installed by running:
45+
1. Install nginx with the [Lua module](https://github.com/openresty/lua-nginx-module) `libnginx-mod-http-lua` and the `luajit` and `luarocks` packages.
46+
1. Debian: `apt-get install nginx libnginx-mod-http-lua luajit luarocks`
47+
2. Fedora: `dnf install nginx libnginx-mod-http-lua luajit luarocks`
48+
2. Install the [LuaFileSystem](https://lunarmodules.github.io/luafilesystem/) module via `luarocks install luafilesystem`
49+
3. Verify that the Lua module is properly installed by running:
5250
```bash
5351
nginx -V 2>&1 | tr ' ' '\n' | grep lua
5452
```
@@ -58,20 +56,23 @@ Physical memory usage of this plugin is insanely low, under 10 KB for each nginx
5856
--add-module=/lua-upstream-nginx-module-0.07
5957
--add-module=/stream-lua-nginx-module-9ce0848cff7c3c5eb0a7d5adfe2de22ea98e1abc
6058
```
61-
2. Build and install the plugin into an appropriate directory accessible by the nginx process, e.g.,
59+
4. Build and install the plugin into an appropriate directory accessible by the nginx process, e.g.,
6260
```bash
6361
luajit -b htaccess.lua /etc/nginx/lua/htaccess.lbc
6462
```
65-
3. Add the following configuration to the nginx `http {}` context:
63+
5. Add the following configuration to the nginx `http {}` context:
6664
```nginx
6765
http {
6866
...
6967
lua_shared_dict htaccess 16m;
68+
69+
# This is useful for debugging but may cause performance problems
70+
# lua_code_cache off;
7071
...
7172
}
7273
```
7374
This represents a caching system, used on a short-term per-request basis. `.htaccess` lines are usually cached as values for less than 100 milliseconds, but kept in memory as long as there are active connections. You can choose to assign any other memory amount to it, although 16 MB should be more than enough.
74-
4. Configure the nginx `server {}` context(s) to use the plugin:
75+
6. Configure the nginx `server {}` context(s) to use the plugin:
7576
```nginx
7677
server {
7778
...
@@ -242,7 +243,7 @@ mod_negotiation | `ForceLanguagePriority` | No |
242243
mod_negotiation | `LanguagePriority` | No |
243244
mod_reflector | `*` | Never | Security reasons
244245
mod_rewrite | `RewriteBase` | Yes |
245-
mod_rewrite | `RewriteCond` | Partial | Environment (E=) flag is unsupported, as are *CondPattern* integer comparisons and some file attribute tests listed in the [documentation](https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html)
246+
mod_rewrite | `RewriteCond` | Partial | Environment (E=) flag is unsupported, as are *CondPattern* integer comparisons and some file attribute tests listed in the [documentation](https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html).
246247
mod_rewrite | `RewriteEngine` | Yes |
247248
mod_rewrite | `RewriteOptions` | No |
248249
mod_rewrite | `RewriteRule` | Yes |
@@ -321,64 +322,3 @@ Variables not listed below are not supported.
321322
...
322323
}
323324
```
324-
325-
326-
## Debugging Lua inside a Docker container
327-
328-
Using IntelliJ IDEA, you can remotely debug Lua scripts like `htaccess.lua` running in an nginx Docker container, using [these steps](https://dev.to/omervk/debugging-lua-inside-openresty-inside-docker-with-intellij-idea-2h95). In particular, this has been tested on a Windows 10 host running IntelliJ IDEA 2022.2.4 (Community Edition), with the `fabiocicerchia/nginx-lua:1.23.2-almalinux8.7-20221201` Docker image from https://hub.docker.com/r/fabiocicerchia/nginx-lua.
329-
330-
It assumes you are mapping a host path of `C:\path\to\project\on\windows` to a path in the container volume of `/path/to/project`.
331-
332-
1. Install [IntelliJ IDEA](https://www.jetbrains.com/idea/download/#section=windows)
333-
1. The container needs to forward port 9966 to allow for Lua debugging. If you are using `docker-compose.yml` it will look something like this:
334-
```yml
335-
version: '2.4'
336-
services:
337-
nginx-lua:
338-
build:
339-
context: .
340-
container_name: nginx-lua
341-
ports:
342-
# For nginx requests over HTTP
343-
- 80:80
344-
# If you support nginx requests over HTTPS
345-
- 443:443
346-
# For Lua debugging
347-
- 9966:9966
348-
volumes:
349-
- ./relative/path/to/project/on/windows/:/path/to/project/
350-
```
351-
1. In the `Dockerfile` for the container, run the following command to build the EmmyLuaDebugger from source:
352-
```bash
353-
RUN dnf install -y cmake && \
354-
curl https://github.com/EmmyLua/EmmyLuaDebugger/archive/refs/tags/1.0.16.tar.gz \
355-
-L -o EmmyLuaDebugger-1.0.16.tar.gz && \
356-
tar -xzvf EmmyLuaDebugger-1.0.16.tar.gz && \
357-
cd EmmyLuaDebugger-1.0.16 && \
358-
mkdir -p build && \
359-
cd build && \
360-
cmake -DCMAKE_BUILD_TYPE=Release ../ && \
361-
make install && \
362-
mkdir -p /usr/local/emmy && \
363-
cp install/bin/emmy_core.so /usr/local/emmy/ && \
364-
cd .. && \
365-
cd .. && \
366-
rm -rf EmmyLuaDebugger-1.0.16 EmmyLuaDebugger-1.0.16.tar.gz
367-
```
368-
1. Start the container
369-
1. At the top of your Lua script to debug, add the following:
370-
```lua
371-
_G.emmy = {}
372-
_G.emmy.fixPath = function(path)
373-
return string.gsub(path, '/path/to/project/', 'C:/path/to/project/on/windows')
374-
end
375-
376-
package.cpath = package.cpath .. ';/usr/local/emmy/?.so'
377-
local dbg = require('emmy_core')
378-
dbg.tcpListen('localhost', 9966)
379-
dbg.waitIDE()
380-
dbg.breakHere()
381-
```
382-
1. In IDEA, create a Run/Debug configuration per the link and then start the debugger
383-
384-
When you request a URL that triggers the Lua script, it will pause on the `dbg.breakHere()` line so you can step through the code, watch variables, etc.

htaccess.lua

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,27 @@ local path_exists = function(filepath, soft_fail)
137137
return ok
138138
end
139139

140+
-- Get the type of a file system object
141+
-- @param filepath .... the filename
142+
-- @return file_type .. One of (directory|link|file), or nil if the path is invalid
143+
local get_file_type = function(filepath)
144+
local lfs = require "lfs"
145+
local file_type = nil
146+
if (lfs.symlinkattributes (filepath) ~= nil) then
147+
local attr = lfs.symlinkattributes (filepath);
148+
assert (type(attr) == "table")
149+
if attr.mode == "directory" then
150+
file_type = 'directory'
151+
elseif attr['target'] ~= nil then
152+
-- print ("*** symlink found "..attr['target'])
153+
file_type = 'link'
154+
else
155+
file_type = 'file'
156+
end
157+
end
158+
return file_type
159+
end
160+
140161
-- Read contents of any file
141162
local get_file_contents = function(name)
142163
ensure_doc_root(name) -- Security: enforce document root
@@ -328,14 +349,6 @@ local push_cdir = function(directive_type, value)
328349
end
329350
end
330351

331-
-- Helper function to get computed directive value and actual context table
332-
-- local resolve_cdir_value = function(value_table)
333-
-- if not value_table then
334-
-- return nil
335-
-- end
336-
-- return value_table[C_VALUE], ctx_map[value_table[C_CTX_INDEX]]
337-
-- end
338-
339352
-- Return computed directive by type
340353
-- directive_type ... string of requested type (lowercase), e.g. 'rewriterules'
341354
-- index_or_flag .... index of indexed directive (e.g. 'username') or C_MULTIPLE, for which the entire computed table will be returned
@@ -770,7 +783,7 @@ local replace_server_vars = function(str, track_used_headers)
770783
replace = os.date('%w')
771784
end
772785
elseif whitelist[svar] then
773-
replace = ngx.var[svar]
786+
replace = ngx.var[svar] or ''
774787
elseif svar == 'request_uri' then -- %{REQUEST_URI}
775788
-- Use ngx.var['uri'] to match the Apache convention since it doesn't contain the query string
776789
replace = ngx.var['uri']
@@ -1088,10 +1101,16 @@ if get_cdir('rewrite') and #parsed_rewriterules > 0 then
10881101
fail('RewriteCond expressions ("expr ...") are unsupported') -- We don't support expr style conditions due to their weird complexity and redundancy
10891102
elseif cond_pattern:sub(1,1) == '-' then -- File attribute tests or integer comparisons (case sensitive)
10901103
local filepath = cond_test:gsub('/$','',1)
1104+
local file_type = get_file_type(filepath)
1105+
1106+
cond_matches = false
1107+
10911108
if cond_pattern == '-d' then -- is directory
1092-
cond_matches = path_exists(filepath..'/')
1109+
cond_matches = file_type == 'directory'
10931110
elseif cond_pattern == '-f' or cond_pattern == '-F' then -- is file
1094-
cond_matches = path_exists(filepath) and not path_exists(filepath..'/')
1111+
cond_matches = file_type == 'file'
1112+
elseif cond_pattern == '-l' or cond_pattern == '-L' then -- is symlink
1113+
cond_matches = file_type == 'link'
10951114
else
10961115
fail('RewriteCond pattern unsupported: '..cond_pattern)
10971116
end

0 commit comments

Comments
 (0)