Deny clients listed in a file
An access handler runs in nginx’s access phase, before the content of the
location. A Ruby script there can end the request with a status, for
example 403, or let it go on by returning without a status
(mruby_access_handler).
The sample
Section titled “The sample”The access handler reads the file that the variable $deny_list names and
answers 403 when the client’s address is one of its lines. The location
/listed/ names a list that holds 127.0.0.1, the address of the test
client, so the request gets 403; error_page 403 @denied gives that 403
its body. The location /open/ names a list without that address.
server { listen 18162; default_type text/plain; error_page 403 @denied;
# The list of this location holds 127.0.0.1, the address of the case. location /listed/ { set $deny_list build/nginx/html/guide_access_listed.txt; mruby_access_handler build/nginx/html/guide_access.rb; mruby_content_handler_code 'Nginx.rputs "welcome\n"'; }
# The list of this location does not hold it. location /open/ { set $deny_list build/nginx/html/guide_access_open.txt; mruby_access_handler build/nginx/html/guide_access.rb; mruby_content_handler_code 'Nginx.rputs "welcome\n"'; }
location @denied { return 403 "your address is on the deny list\n"; }}r = Nginx::Request.newpath = r.var.deny_listlisted = File.exist?(path) && File.read(path).split("\n").include?(r.var.remote_addr)Nginx.return Nginx::HTTP_FORBIDDEN if listedGET /listed/report HTTP/1.1Host: 127.0.0.1:18162Connection: closeHTTP/1.1 403 ForbiddenContent-Type: text/plain
your address is on the deny listOn every CI run, the case test/t/cases/guides.rb sends this request and compares the status line, the headers shown on this page and the whole body. The five files last changed on 2026-10-29 in commit 32219e53.
The case also sends GET /open/report and expects 200 with the body
welcome.
What to keep in mind
Section titled “What to keep in mind”- The script reads the list file for every request, which blocks the
worker while the disk answers. To read it once per worker, load the list
in
mruby_init_worker_codeinto a constant, and reload nginx after a change of the file (What a worker keeps between requests). r.var.remote_addris the address of the TCP peer. Behind a load balancer, that is the load balancer, unless nginx’s realip module sets it from a header that the load balancer sends.Nginx.return Nginx::HTTP_FORBIDDENends the request with 403. A script that returns withoutNginx.returnlets nginx go on with the next handler of the access phase and then the content.