コンテンツにスキップ
2.x保守ブランチのドキュメントです。最新リリースタグは v2.7.2。v2.7.3 の変更は未リリースです。導入例の対象バージョンを確認してください。開発中の3.xは、3.xのドキュメントを読んでください。

Mruby API documentation for ngx_mruby

2.xのドキュメントは、リリースノートを除いて英語で載せています。このページにも日本語訳はありません。

This is the mruby API documentation for ngx_mruby.

ngx_mruby provides mruby APIs to access and manipulate nginx internal data structure. You can use these classes and methods in handlers like mruby_content_handler_code.

Available APIs depend on your build configuration. See Configuring mrbgems and Build options for the build configuration.

TODO: Sort. I don’t think alphabetical order is easy to read.

The ngx_mruby HTTP module is a nginx module to extend the HTTP server by mruby and the core of ngx_mruby.

Notice: ngx_mruby_mrblib is a required mrbgem and a part of The HTTP module. The classes and methods provided by ngx_mruby_mrblib are documented here.

The ngx_mruby stream module is an optional nginx module to handle TCP and UDP stream.

The rack-based-api mrbgem is an optional bundled mrbgem. It provides RACK (Ruby Webserver Interface) compatible APIs to make development and testing easier.

The auto-ssl mrbgem is an optional bundled mrbgem to support Automatic Certificate Management Environment (ACME) protocol client. You can easily get SSL certificates from Let’s Encrypt.

Nginx::SSL::ACME::Client speaks ACMEv1, which Let’s Encrypt fully turned off on 1 June 2021 (End of Life Plan for ACMEv1), so it gets no certificate from Let’s Encrypt. The helpers for the dehydrated ACME client (Nginx::SSL::ACME::Dehydrated) do not use it.

It is still in early development phase. See script files in mrbgems/auto-ssl/mrblib for APIs.

You can use the following classes with default build configuration.

The Redis class was left out of the default build in 2.7.1 and is in it again since 2.7.2 (see “Redis is in the default build again” in the 2.7.2 release notes).

You can also use classes embedded by default.gembox and full-core.gembox.

ngx_mruby HTTP module adds two methods to Kernel module. These methods are called without a receiver. Both are provided to write portable code for mod_mruby.

Returns server software class Nginx.

Server = get_server_class
Server.echo "hello world" # Nginx.echo is called

Returns server software name NGINX as a string.

if server_name == "NGINX"
Server = Nginx
elsif server_name == "Apache"
Server = Apache
end

Puts response text. If a post-read, server rewrite, rewrite, access or content handler raises an exception afterwards, the request gets 500 and the text is not sent, unless the response was already started, for example by the location that Nginx.redirect ran. Since 2.7.1 this also holds for a handler that raises before it waits in Nginx::Async; in 2.7.0 such a handler sent the text with status 200. In an mruby_set* handler, a log handler or an output filter, the text is not sent after an exception either, and the request goes on as after an exception without output: Content-Length does not count the text (since 2.7.1). For an mruby_set* handler this holds when the code raises before it waits in Nginx::Async. When it raises after Nginx::Async.sleep, the request gets 500; when it raises after Nginx::Async::HTTP.sub_request, nginx has already gone on with the content phase without waiting for the variable, so the 500 is not sent and the client gets no response, as described under Nginx::Async#sleep. To end a content handler early after writing the text, leave it with return instead of raise.

Nginx.rputs "hello ngx_mruby world!"

An argument that is not a String is converted with to_s, so Nginx.rputs nil writes nothing, as print nil does in CRuby. A content handler that writes nothing and sets no status answers 500 (see Nginx.return).

Puts response text with a newline. Like Nginx.rputs, the text is not sent when the handler raises an exception afterwards (since 2.7.1).

Nginx.echo "hello ngx_mruby world!"

is equal to

Nginx.rputs "hello ngx_mruby world!\n"

Returns nginx status code to send back HTTP status to the client or control nginx request processing flow. The status code consists of nginx internal status and HTTP status.

Nginx.return Nginx::HTTP_SERVICE_UNAVAILABLE # returns HTTP status 503

A content handler that ends without output answers 500 with nginx’s error page, unless it set a status that nginx answers by itself: Nginx::HTTP_CREATED, Nginx::HTTP_NO_CONTENT (204 without a body) or a status from 300 up. This covers Nginx::HTTP_OK and the other 2xx statuses as well as a handler that sets no status. error.log gets a line at the error level that ends with response body is empty. return NGX_HTTP_INTERNAL_SERVER_ERROR. To answer with an empty body, use Nginx::HTTP_NO_CONTENT:

location /empty {
mruby_content_handler_code 'Nginx.return Nginx::HTTP_NO_CONTENT'; # 204 without a body
}

A content handler on the main request that writes output with Nginx.rputs or Nginx.echo and then calls Nginx.return (or Nginx.send_header, Nginx.status_code=) answers as follows, also after Nginx::Async::HTTP.sub_request resumed it:

  • Nginx::HTTP_OK, or another status below 300 other than Nginx::HTTP_CREATED and Nginx::HTTP_NO_CONTENT: the output, with that status and Content-Length of the output, like nginx’s own return 202 "text"; without its Content-Type. A status below 200 goes out the same way, although HTTP does not allow a final response with it. Nginx.return 0 sets no status, and the output gets 200. Since 2.7.2; in 2.7.1 these statuses, other than 200, left the client without a response.
  • Nginx::HTTP_CREATED, Nginx::HTTP_NO_CONTENT or a status from 300 up: nginx’s own response for that status, without the output.

A status set before the first Nginx.rputs or Nginx.echo does not apply to the output: the response is 200.

location /accepted {
mruby_content_handler_code '
Nginx.rputs "queued"
Nginx.return Nginx::HTTP_ACCEPTED # 202 with the body "queued"
';
}

In a subrequest (Nginx::Async::HTTP.sub_request, an SSI include, auth_request), only Nginx::HTTP_OK without output answers 500. A content handler that writes nothing there and sets no status or another status below 300 ends the subrequest without a response body, and the parent request answers. After output, a status other than Nginx::HTTP_OK ends the subrequest without a response body as well.

Don’t confuse Nginx.return method with mruby’s return statement. ngx_mruby v2 supports return statement in handler code as below. It just returns from the handler.

location /foo {
mruby_content_handler_code '
Nginx.rputs "foo" # generates HTTP body "foo"
Nginx.return Nginx::HTTP_OK # returns HTTP status 200
return if true # returns from this handler
Nginx.rputs "bar" # not reached
';
}

In 2.x, a return inside a block or inside the body of for at the top level of handler code does not return from the handler: mruby 3.3.0, which 2.x bundles, raises LocalJumpError (unexpected return) there, and error.log records it as mrb_run failed. The handler then fails as after any other exception: a rewrite or content handler answers 500, and the output that the code wrote before the return is not sent (2.7.0 sent it with 200; see Nginx.rputs). Calling Nginx.return there does not end the code either: it sets the status, and the code after the block still runs. To end the handler from a block, leave the block with break and return at the top level of the code, or put the code in a method (or in a lambda, ->() do ... end.call) and call it, so that the return returns from the method or the lambda:

location /foo_break {
mruby_content_handler_code '
done = false
["foo"].each do |body|
Nginx.rputs body # generates HTTP body "foo"
Nginx.return Nginx::HTTP_OK # returns HTTP status 200
done = true
break # leaves the block
end
return if done # returns from this handler
Nginx.rputs "bar" # not reached
';
}
location /foo_method {
mruby_content_handler_code '
def foo
["foo"].each do |body|
Nginx.rputs body # generates HTTP body "foo"
Nginx.return Nginx::HTTP_OK # returns HTTP status 200
return # returns from the method foo
end
Nginx.rputs "bar" # not reached
end
foo
';
}

ngx_mruby 3.0.0 handles such a return as the end of the handler code; see the entry “A return inside a block or a for body of handler code ends the code” in docs/releases/v3.0.0.md on next.

Alias for Nginx.return

Alias for Nginx.return

Sends an error to the log file via ngx_log_error(). The method accepts one of log levels and a message to send as arguments.

Nginx.errlogger Nginx::LOG_ERR, "ngx_mruby error!"

You will see an error message in error.log as below.

2014/03/03 00:07:09 [error] 37667#0: *2 ngx_mruby error!, client: 192.168.12.9, server: localhost, request: "GET /log-test HTTP/1.1", host: "192.168.12.9:8001"

The code of mruby_init*, mruby_init_worker*, mruby_exit_worker*, mruby_ssl_handshake_handler* and mruby_server_context_handler_code runs outside a request. There the method writes the message to nginx’s error log, without the client and request part (since 2.7.1; 2.7.0 raised a RuntimeError when the process had not handled a request yet, and otherwise wrote through the last request that the process had handled).

Code outside a request can also call Nginx.module_name, Nginx.module_version, Nginx.nginx_version, Nginx.server_version, Nginx.configure, Nginx.remove_global_variable and server_name, use the constants, and use classes that do not depend on a request, such as Userdata. Since 2.7.1 the request-scoped methods raise a RuntimeError (this method can only be used while processing a request) there: the methods of Nginx::Request, Nginx::Var, Nginx::Headers_in, Nginx::Headers_out, Nginx::Connection, Nginx::Server, Nginx::Filter, Nginx::Upstream and Nginx::Async, and Nginx.rputs, Nginx.echo, Nginx.return, Nginx.send_header, Nginx.status_code= and Nginx.redirect. In 2.7.0 they crashed the process when it had not handled a request yet, and otherwise returned or changed data of the last request that the process had handled. Nginx::Server#add_listener works only in mruby_server_context_handler_code, and Nginx::SSL only in mruby_ssl_handshake_handler*.

Alias for Nginx.errlogger. Outside a request it writes to nginx’s error log, as described under Nginx.errlogger (since 2.7.1).

Returns module name ngx_mruby.

Nginx.echo Nginx.module_name #=> ngx_mruby

Returns ngx_mruby version as a string.

Nginx.echo Nginx.module_version #=> 0.0.1

Returns nginx version as a string.

Nginx.echo Nginx.nginx_version #=> 1.4.4

Returns server software version as a string. Alias for Nginx.nginx_version. It’s provided to write portable code for mod_mruby.

Returns nginx build configuration as a string. It’s same as output of nginx -V configure arguments.

Nginx.echo Nginx.configure #=> --add-module=/home/matsumoto_r/DEV/ngx_mruby \
# --add-module=/home/matsumoto_r/DEV/ngx_mruby/dependence/ngx_devel_kit \
# --prefix=/usr/local/nginx-1.4.4

Nginx.redirect(url_or_internal_location, http_status=Nginx::HTTP_MOVED_TEMPORARILY)

Section titled “Nginx.redirect(url_or_internal_location, http_status=Nginx::HTTP_MOVED_TEMPORARILY)”

Redirects to the URL or the internal location. It is designed to be used in the rewrite handlers.

The URL redirect returns HTTP status codes 3xx like 307 Temporary Redirect with Location header to the client.

Nginx.redirect "http://ngx.mruby.org/", Nginx::HTTP_MOVED_PERMANENTLY

The internal redirect never returns response to the client. The original request is internally forwarded to other location, then the location returns to a response to the client. See error_page and internal directives, and Creating NGINX Rewrite Rules for more about the internal redirect.

The internal redirect runs the handlers of the other location before the call returns. When an mruby handler or filter of that location raises an exception, the exception ends that handler as it does without the redirect: the request gets 500 unless its response was already started. The exception does not reach the code that called Nginx.redirect, which goes on after the call. This holds since 2.7.3; up to 2.7.2 the exception reached the calling code, which could rescue it, and nginx did not finish the request.

location /secret-location {
internal;
mruby_content_handler_code '
r = Nginx::Request.new
Nginx.echo "Returns from /secret-location."
Nginx.return Nginx::HTTP_OK
';
}
location /public-location {
mruby_content_handler_code '
Nginx.redirect "/secret-location"
';
}

Removes a mruby’s global variable.

$a = 1
Nginx.echo global_variables #=> [:$stdout, :$$, :$/, :$stdin, :$?, :$a, :$stderr, :$1, :$2, :$3, :$4, :$5, :$6, :$7, :$8, :$9]
Nginx.remove_global_variable :$a
Nginx.echo global_variables #=> [:$stdout, :$$, :$/, :$stdin, :$?, :$stderr, :$1, :$2, :$3, :$4, :$5, :$6, :$7, :$8, :$9]

Log levels for Nginx.errlogger that mirror nginx error log levels. See nginx log levels and core/ngx_log.h.

Name Description
Nginx::LOG_STDERR Defined in core/ngx_log.h, but it’s never used
Nginx::LOG_EMERG Emergency error log level
Nginx::LOG_ALERT Alert error log level
Nginx::LOG_CRIT Critical error log level
Nginx::LOG_ERR Error log level
Nginx::LOG_WARN Warning log level
Nginx::LOG_NOTICE Notice log level
Nginx::LOG_INFO Information log level
Nginx::LOG_DEBUG Debug log level

HTTP status and internal nginx status for Nginx.return. See nginx HTTP Return Codes for the HTTP statuses. The statuses from Nginx::OK (0) to Nginx::ABORT (-6) are internally used to control nginx processing flow. They are defined in core/ngx_core.h.

Name Value
Nginx::OK 0
Nginx::ERROR -1
Nginx::AGAIN -2
Nginx::BUSY -3
Nginx::DONE -4
Nginx::DECLINED -5
Nginx::ABORT -6
Nginx::HTTP_CONTINUE 100
Nginx::HTTP_SWITCHING_PROTOCOLS 101
Nginx::HTTP_PROCESSING 102
Nginx::HTTP_OK 200
Nginx::HTTP_CREATED 201
Nginx::HTTP_ACCEPTED 202
Nginx::HTTP_NO_CONTENT 204
Nginx::HTTP_PARTIAL_CONTENT 206
Nginx::HTTP_SPECIAL_RESPONSE 300
Nginx::HTTP_MOVED_PERMANENTLY 301
Nginx::HTTP_MOVED_TEMPORARILY 302
Nginx::HTTP_SEE_OTHER 303
Nginx::HTTP_NOT_MODIFIED 304
Nginx::HTTP_TEMPORARY_REDIRECT 307
Nginx::HTTP_BAD_REQUEST 400
Nginx::HTTP_UNAUTHORIZED 401
Nginx::HTTP_FORBIDDEN 403
Nginx::HTTP_NOT_FOUND 404
Nginx::HTTP_NOT_ALLOWED 405
Nginx::HTTP_REQUEST_TIME_OUT 408
Nginx::HTTP_CONFLICT 409
Nginx::HTTP_LENGTH_REQUIRED 411
Nginx::HTTP_PRECONDITION_FAILED 412
Nginx::HTTP_REQUEST_ENTITY_TOO_LARGE 413
Nginx::HTTP_REQUEST_URI_TOO_LARGE 414
Nginx::HTTP_UNSUPPORTED_MEDIA_TYPE 415
Nginx::HTTP_RANGE_NOT_SATISFIABLE 416
Nginx::HTTP_TOO_MANY_REQUESTS 429
Nginx::HTTP_CLOSE 444
Nginx::HTTP_NGINX_CODES 494
Nginx::HTTP_REQUEST_HEADER_TOO_LARGE 494
Nginx::HTTPS_CERT_ERROR 495
Nginx::HTTPS_NO_CERT 496
Nginx::HTTP_TO_HTTPS 497
Nginx::HTTP_CLIENT_CLOSED_REQUEST 499
Nginx::HTTP_INTERNAL_SERVER_ERROR 500
Nginx::HTTP_NOT_IMPLEMENTED 501
Nginx::HTTP_BAD_GATEWAY 502
Nginx::HTTP_SERVICE_UNAVAILABLE 503
Nginx::HTTP_GATEWAY_TIME_OUT 504
Nginx::HTTP_INSUFFICIENT_STORAGE 507

Nginx::SSL class is designed to be used in the ssl handshake handlers. Since 2.7.1 its methods raise a RuntimeError when they are called anywhere else, for example in mruby_content_handler_code; in 2.7.0 such a call could crash the worker or return meaningless values. A handshake whose code sets no certificate, also one whose code does not call Nginx::SSL.new, uses the server’s ssl_certificate and ssl_certificate_key (since 2.7.1; in 2.7.0 a handshake whose code did not call Nginx::SSL.new could get the certificate that an earlier handshake on the same worker had set, or fail).

Returns the SNI server name from the client. The client chooses this name, Treat it as untrusted input (see Trust boundary): look it up in a table of known names, and do not build a path from it.

http {
mruby_init_code '
CERT_DIRS = {
"example.com" => "/etc/nginx/certs/example.com",
"www.example.com" => "/etc/nginx/certs/www.example.com",
}
';
server {
listen 443 ssl;
ssl_certificate /etc/nginx/certs/default.crt;
ssl_certificate_key /etc/nginx/certs/default.key;
mruby_ssl_handshake_handler_code '
ssl = Nginx::SSL.new
dir = CERT_DIRS[ssl.servername]
if dir
ssl.certificate = "#{dir}/cert.pem"
ssl.certificate_key = "#{dir}/key.pem"
end
';
}
}

The lookup is exact: the name is compared as the client sent it, including its case. A name that is not in CERT_DIRS, also an empty name from a client that sends none, keeps the certificate of ssl_certificate and ssl_certificate_key.

Sets the certificate file path used for the connection. The worker reads the file during the handshake. Take the path from a table, not from the server name.

mruby_ssl_handshake_handler_code '
ssl = Nginx::SSL.new
dir = CERT_DIRS[ssl.servername]
if dir
ssl.certificate = "#{dir}/cert.pem"
ssl.certificate_key = "#{dir}/key.pem"
end
';

CERT_DIRS is the table of the example under servername.

Sets the certificate key file path used for the connection. Set it together with certificate=; the handshake changes the certificate only when both are set. Take the path from a table, not from the server name.

mruby_ssl_handshake_handler_code '
ssl = Nginx::SSL.new
dir = CERT_DIRS[ssl.servername]
if dir
ssl.certificate = "#{dir}/cert.pem"
ssl.certificate_key = "#{dir}/key.pem"
end
';

CERT_DIRS is the table of the example under servername.

Sets the certificate data used for the connection, as a string in PEM format (the certificate, then its chain). Read the files once in the init code, so that the handshake does not read a file, and look the data up by server name. The init code runs once, so a certificate that changes on disk reaches the handshake after nginx -s reload.

http {
mruby_init_code '
CERT_DATA = {}
["example.com", "www.example.com"].each do |name|
CERT_DATA[name] = [
File.read("/etc/nginx/certs/#{name}/cert.pem"),
File.read("/etc/nginx/certs/#{name}/key.pem"),
]
end
';
server {
listen 443 ssl;
ssl_certificate /etc/nginx/certs/default.crt;
ssl_certificate_key /etc/nginx/certs/default.key;
mruby_ssl_handshake_handler_code '
ssl = Nginx::SSL.new
data = CERT_DATA[ssl.servername]
if data
ssl.certificate_data = data[0]
ssl.certificate_key_data = data[1]
end
';
}
}

Sets the certificate key data used for the connection, as a string in PEM format. Set it together with certificate_data=; the handshake changes the certificate by data only when both are set, and then it does not use the paths.

mruby_ssl_handshake_handler_code '
ssl = Nginx::SSL.new
data = CERT_DATA[ssl.servername]
if data
ssl.certificate_data = data[0]
ssl.certificate_key_data = data[1]
end
';

CERT_DATA is the table of the example under certificate_data=.

Sends an error to the log file via ngx_log_error(). The method accepts one of log levels and a message to send as arguments.

Nginx::SSL.errlogger Nginx::LOG_ERR, "ngx_mruby error!"

Alias for Nginx::SSL.errlogger

Returns the port number used for the connection.

mruby_ssl_handshake_handler_code '
ssl = Nginx::SSL.new
Userdata.new.ssl_local_port = ssl.local_port
';
location /local_port {
mruby_content_handler_code "Nginx.rputs Userdata.new.ssl_local_port.to_s";
}

Returns the name of the protocol like TLSv1.3 used for the connection. This is a wrapper for SSL_get_version(). See SSL_get_version(3) for the return values.

mruby_ssl_handshake_handler_code '
ssl = Nginx::SSL.new
Userdata.new.ssl_tls_version = ssl.tls_version
';
location /tls_version {
mruby_content_handler_code "Nginx.rputs Userdata.new.ssl_tls_version.to_s";
}

Returns the scheme name of the requested URL.

# curl https://127.0.0.1/
r = Nginx::Request.new
r.scheme #=> https

Set the content type to the response.

Notice: Unlike the name suggests, Nginx::Request#content_type=() and Nginx::Request#content_type() handle HTTP response, not request.

location /foo {
mruby_content_handler_code '
r = Nginx::Request.new
r.content_type = "text/plain"
Nginx.rputs "This is a plain text"
';
}
% curl -v http://127.0.0.1:58080/foo
[snip]
< HTTP/1.1 200 OK
< Date: Thu, 29 Nov 2018 07:55:22 GMT
< Content-Type: text/plain
< Content-Length: 20
< Connection: keep-alive
< hoge: fuga
< Server: global_ngx_mruby
<
* Connection #0 to host 127.0.0.1 left intact
This is a plain text

Returns the content type of the response.

r = Nginx::Request.new
r.content_type = "text/plain"
# Do some other things
Nginx.echo r.content_type #=> text/plain

Returns the HTTP request line.

# curl http://127.0.0.1/hello?a=1
r = Nginx::Request.new
Nginx.echo r.request_line #=> GET /hello?a=1 HTTP/1.1

Sets the string to the HTTP request line.

r = Nginx::Request.new
Nginx.echo r.request_line = 'GET /hello?a=1&b=1 HTTP/1.1'

Nginx::Request#sub_request? -> true or false

Section titled “Nginx::Request#sub_request? -> true or false”

Return true if the request is a sub request.

nginx provides a mechanism to internally send a sub request when received a request. See Authentication Based on Subrequest Result for how it works.

r = Nginx::Request.new
# location / { mruby_content_handler /path/to/hook.rb; }
Nginx.echo r.sub_request?.to_s #=> "false"

Returns an URI without the query parameters in the HTTP request line.

# curl http://127.0.0.1/hello?a=1
r = Nginx::Request.new
Nginx.echo r.uri #=> /hello

Set the string to uri.

r = Nginx::Request.new
Nginx.echo r.uri = "/foo"

Returns an URI in the original HTTP request line.

# curl http://127.0.0.1/hello?a=1
r = Nginx::Request.new
Nginx.echo r.unparsed_uri #=> /hello?a=1

Sets the string to unparsed_uri.

r = Nginx::Request.new
Nginx.echo r.unparsed_uri = "/hello?a=1"

Returns the HTTP method of the request as a string like GET.

# curl http://127.0.0.1/hello?a=1
r = Nginx::Request.new
Nginx.echo r.method #=> GET

Sets the string to method.

r = Nginx::Request.new
Nginx.echo r.method = "POST"

Returns the request protocol of the request like HTTP/1.1.

# curl http://127.0.0.1/hello?a=1
r = Nginx::Request.new
Nginx.echo r.protocol #=> HTTP/1.1

Sets the string to the request protocol

# curl http://127.0.0.1/hello?a=1
r = Nginx::Request.new
Nginx.echo r.protocol = "HTTP/1.0"

Returns the URL query parameters. See Nginx::Request#uri_args if you need parsed query parameters.

# curl http://127.0.0.1/hello?a=1&b=2
r = Nginx::Request.new
Nginx.echo r.args #=> a=1&b=2

Sets the string to args.

r = Nginx::Request.new
Nginx.echo r.args "a=10&b=20"

Returns a Var instance of the request. See Nginx::Var Class for more details.

r = Nginx::Request.new
v = r.var
v.exist? "foo" #=> false

Returns a Headers_in instance of the request. See Nginx::Headers_in Class for more details.

r = Nginx::Request.new
in = r.headers_in
in.["User-Agent"] #=> curl/7.52.1

Returns a Headers_out instance of the request. See Nginx::Headers_out Class for more details.

r = Nginx::Request.new
out = r.headers_out
out.["X-NGX-MRUBY-INTERACTION-ID"] = Uuid.uuid

Returns the host name. It’s same as nginx variable $host. Therefore, the order of precedence is: host name in the request line, host name in Host HTTP request header, or server name defined in nginx.conf.

# curl http://127.0.0.1:8001/hello?a=1
r = Nginx::Request.new
Nginx.echo r.hostname #=> "127.0.0.1"

Returns authority without userinfo.

# curl -v http://127.0.0.1:8001/hello?a=1
r = Nginx::Request.new
Nginx.echo r.authority #=> "127.0.0.1:8001"

Returns the requested filename. It’s same as nginx variable $request_filename.

# curl -v http://127.0.0.1/hello?a=1
r = Nginx::Request.new
Nginx.echo r.filename #=> /usr/local/nginx-1.4.4/html/hello

Returns the user name of the Basic authentication.

# curl http://127.0.0.1/hello?a=1 -u matsumoto_r
r = Nginx::Request.new
Nginx.echo r.user #=> matsumoto_r

Does nothing and always returns Nginx::OK. It is only for backward compatibility.

Returns the request body as a string.

Notice: If you want to use the the method, you must use mruby_enable_read_request_body directive in nginx.conf to force reading the request body as below.

location /foo {
mruby_enable_read_request_body on; # Force reading the request body
mruby_access_handler_code '
req = Nginx::Request.new
body = req.get_body # Get the body
Nginx.log Nginx::LOG_ERR, "body:#{body}"
Userdata.new.req_body = body # Set the body to Userdata used in the content handler
';
mruby_content_handler_code '
Nginx.rputs Userdata.new.req_body
';
}

Alias for Nginx::Request#get_body.

Returns the document root directory. It is configured by root directive. See the ngx_http_core_module documentation for the directive.

r = Nginx::Request.new
r.document_root #=> /usr/local/nginx-1.4.4

Returns the URL query parameters as a hash.

# curl http://127.0.0.1/hello?a=1&b=2
r = Nginx::Request.new
Nginx.echo r.uri_args #=> {"a" => "1", "b" => "2"}

Set the hash to uri_args.

r = Nginx::Request.new
r.uri_args = {"a" => "10", "b" => "20"}

Returns the request body as a hash. The method assume the content type is application/x-www-form-urlencoded.

# curl http://127.0.0.1/hello?a=1&b=2
r = Nginx::Request.new
Nginx.echo r.uri_args #=> {"a" => "1", "b" => "2"}
Section titled “Return value examples of the URL related methods”

Here is the return value examples of the above URL related methods. if you send a HTTP/1.1 GET request to https://user:pass@api.example.com:8080/foo?a=1&b=2, you will get the following values.

Method Return Value
scheme https
request_line GET /foo?a=1&b=2 HTTP/1.1
uri /foo
unparsed_uri /foo?a=1&b=2
method GET
protocol HTTP/1.1
args foo?a=1&b=2
hostname api.example.com
authority api.example.com:8080
filename /path/to/document/root/foo
user user
uri_args {“a” => “1”, “b” => “2”}
document_root /path/to/document

Create a listener on the specified IP address and the port in the hash. The method works only in mruby_server_context_handler_code, while nginx reads the configuration. Anywhere else, for example in a request handler, it raises a RuntimeError (add_listener can only be used in mruby_server_context_handler_code, since 2.7.1).

s = Nginx::Server.new
s.add_listener({address: "127.0.0.1:58101"})
s.add_listener({address: "58102"})
s.add_listener({address: "58103", ssl: true})

Here is an example to create multiple listeners on port 20001 to 30000.

http {
server {
mruby_server_context_handler_code '
s = Nginx::Server.new
(20001..30000).each { |port| s.add_listener({address: port.to_s}) }
';
location /mruby {
mruby_content_handler_code '
Nginx.rputs "Hello on port #{Nginx::Connection.new.local_port}"
';
}
}
}

Returns the document root directory.

# curl http://127.0.0.1:8001/hello?a=1
s = Nginx::Server.new
Nginx.echo s.document_root # => /usr/local/nginx-1.4.4/html

Returns the document root directory with symlinks resolved to real paths. It’s same as nginx variable $realpath_root.

# curl http://127.0.0.1:8001/hello?a=1
s = Nginx::Server.new
Nginx.echo s.realpath_root # => /usr/local/nginx-1.4.4/html

Alias for Nginx::Server#realpath_root.

Returns the client IP address. It’s same as nginx variable $remote_addr.

# curl http://192.168.0.2:8001/hello?a=1 on 192.168.0.1
c = Nginx::Connection.new
Nginx.echo c.remote_ip # => 192.168.0.1

Return the client port number. It’s same as nginx variable $remote_port.

# curl http://192.168.0.2:8001/hello?a=1 on 192.168.0.1
c = Nginx::Connection.new
Nginx.echo c.remote_port # => 54430

Returns the IP address that accepts the request. It’s same as nginx variable $server_addr.

# curl http://192.168.0.2:8001/hello?a=1 on 192.168.0.1
c = Nginx::Connection.new
Nginx.echo c.local_ip # => 192.168.0.2

Returns the port number that accepts the request. It’s same as nginx variable $server_port.

# curl http://192.168.0.2:8001/hello?a=1 on 192.168.0.1
c = Nginx::Connection.new
Nginx.echo c.local_port # => 8001

nginx supports embedded variables such as $http_host. You can get or set the variables via Var class. See Embedded Variables for variables supported by the ngx_http_core_module.

You can use Var instance as below.

v = Nginx::Var.new
Nginx.echo "$http_host core variable is #{v.http_host}"
v.http_host = "192.168.0.1"
Nginx.echo "$http_host is overridden to #{v.http_host}"

Also you can use your own variable.

Notice: You must use set or mruby_set_code directive to define the variable within the accessible context in nginx.conf. You can NOT add a new variable from mruby code.

location /foo {
set $backend_user = "foo"
mruby_set_code $auth '
r = Nginx::Request.new
backend_user = r.var.backend_user
backend_pass = lookup_pass_for(user)
'Basic ' + Base64.encode(backend_user + ':' + backend_pass)
';
proxy_set_header Authorization $auth;
proxy_pass http://backend.example.com;
}

Nginx::Var#method_missing(symbol [, *args]) -> result

Section titled “Nginx::Var#method_missing(symbol [, *args]) -> result”

It is designed for providing accessor to nginx variable. The method is called when Nginx::Var#VARNAME or Nginx::Var#VARNAME= is evaluated. Set the 2nd arg to the variable if the symbol ends with =. Otherwise, returns the value.

The variable is looked up by the name in lowercase. Since 2.7.2, a name that is empty or made only of = raises NoMethodError, and a setter called without a value raises ArgumentError and leaves the variable as it was.

Set the value to the nginx variable.

name is looked up in lowercase. Since 2.7.2, set does not change the String or Symbol passed as name.

v = Nginx::Request.new.var
v.set "backend", "http://192.168.0.9/" # Set "http://192.168.0.9/" to $backend

Returns true if the variable is defined. If backend variable is not defined in nginx.conf, you will get false.

v = Nginx::Request.new.var
v.exist? "backend" # => false

Headers_in class stores HTTP request headers. The name comes from ngx_http_headers_in_t.

Returns the value of the http request header.

hin = Nginx::Headers_in.new
Nginx.rputs hin["User-Agent"] #=> curl/7.29.0

Sets the value to the http request header.

hin = Nginx::Headers_in.new
Nginx.rputs hin["User-Agent"] #=> curl/7.29.0
hin["User-Agent"] = "test-agent"
Nginx.rputs hin["User-Agent"] #=> test-agent

Returns the all http request headers.

hin = Nginx::Headers_in.new
hin.all.keys.each do |k|
Nginx.echo "#{k}: #{hin[k]}"
end
$ curl http://127.0.0.1:8001/hello
#Host: 127.0.0.1:8001
#User-Agent: curl/7.29.0
#Accept: */*

Delete the field from the http request headers.

hin = Nginx::Headers_in.new
hin["X-Remove-Header"] = "to be deleted!"
hin.delete("X-Remove-Header")
Nginx.rputs hin["X-Remove-Header"] #=> nil

Headers_out class stores HTTP response headers. The name comes from ngx_http_headers_out_t.

Returns the value of the http response header.

hout = Nginx::Headers_out.new
hout["X-NGX-MRUBY"] = "support"
Nginx.rputs hout["X-NGX-MRUBY"] #=> support

Sets the value to the http response header.

hout = Nginx::Headers_out.new
hout["X-NGX-MRUBY"] = "support"
Nginx.rputs hout["X-NGX-MRUBY"] #=> support

Returns the all http response headers.

hout = Nginx::Headers_out.new
hout["X-NGX-MRUBY"] = "support"
hout.all.keys.each do |k|
Nginx.echo "#{k}: #{hout[k]}"
end
$ curl -v http://192.168.12.9:8001/hello?a=1
#X-NGX-MRUBY: support

Delete the field from the http response headers.

hout = Nginx::Headers_out.new
hout["X-Remove-Header"] = "to be deleted!"
hout.delete("X-Remove-Header")
Nginx.rputs hout["X-Remove-Header"] #=> nil

Nginx::Filter class is designed to be used in the output body handlers. Before the body filter has read the body, Nginx::Filter#body returns an empty string: in a content handler, as before, and in a header filter (since 2.7.1). Outside an output body filter, Nginx::Filter#body= and #output raise a RuntimeError (since 2.7.1).

Notice: You can NOT use Nginx.rputs and Nginx.echo in the output header and body handlers (mruby_output_header_filter, mruby_output_body_filter and their _code forms).

Here is an example how it works.

location /foo {
return 200 hello;
}
location /bar {
mruby_output_header_filter_code '
Nginx::Request.new.headers_out["X-Filter"] = "on"
';
mruby_output_body_filter_code '
f = Nginx::Filter.new
f.body = f.body.upcase
';
return 200 hello;
}
$ curl -v http://127.0.0.1:59090/foo
[snip]
< HTTP/1.1 200 OK
< Server: nginx/1.15.7
< Date: Wed, 05 Dec 2018 06:27:19 GMT
< Content-Type: text/plain
< Content-Length: 5
< Connection: keep-alive
<
* Connection #0 to host 127.0.0.1 left intact
hello
$ curl -v http://127.0.0.1:59090/bar
[snip]
< HTTP/1.1 200 OK
< Server: nginx/1.15.7
< Date: Wed, 05 Dec 2018 06:27:24 GMT
< Content-Type: text/plain
< Content-Length: 5
< Connection: keep-alive
< X-Filter: on
<
* Connection #0 to host 127.0.0.1 left intact
HELLO

Returns the response body. In a header filter, which runs before the body has been read, it returns an empty string (since 2.7.1; 2.7.0 returned a string as long as Content-Length whose bytes were not the body, or raised an ArgumentError when the length was unknown or 10 MB or more). To learn the length there, read Nginx::Var.new.sent_http_content_length.

f = Nginx::Filter.new
response = f.body.upcase

Sets the string to the response body. The response is sent with exactly this body, and Content-Length is its length; since 2.7.1 this also holds when the body was written with Nginx.rputs or Nginx.echo. It can only be used in an output body filter; anywhere else it raises a RuntimeError (since 2.7.1).

f = Nginx::Filter.new
f.body = "The original body is removed"

Alias for Nginx::Filter#body=.

You can access upstream configuration via Nginx::Upstream. Here is an example.

http {
upstream my_upstream {
server 127.0.0.1:80;
}
server {
location /foo {
mruby_rewrite_handler_code '
u = Nginx::Upstream.new "my_upstream"
u.server = "127.0.0.1:58081" # Change 'server' to 127.0.0.1:58081 from 127.0.0.1:80
Nginx.return Nginx::DECLINED
';
proxy_pass http://my_upstream;
}
}
}

Creates and returns an Upstream instance.

The string is the whole name of an upstream {} block, compared case-insensitively as nginx compares upstream names. The method raises RuntimeError when no upstream has that name, and TypeError when the argument is not a String. Up to 2.7.2 the method compared only the length of the argument, so it also found the first upstream whose name started with it, and it did not check the class of the argument.

u = Nginx::Upstream.new "YOUR_UPSTREAM_NAME"

Nginx::Upstream#keepalive_cache -> integer

Section titled “Nginx::Upstream#keepalive_cache -> integer”

Returns the keepalive cache of the upstream.

u = Nginx::Upstream.new "YOUR_UPSTREAM_NAME"
n = u.keepalive_cache

Sets the keepalive cache of the upstream.

u = Nginx::Upstream.new "YOUR_UPSTREAM_NAME"
u.keepalive_cache = 0

Returns the server of the upstream.

u = Nginx::Upstream.new "YOUR_UPSTREAM_NAME"
Nginx.echo u.server #=> 127.0.0.1:80

Sets the string to the server of the upstream.

The servers of the upstream block that are not backup must have one address in all: Nginx::Upstream.new raises RuntimeError for more, for example for two server lines, or for one whose host name nginx resolved to two addresses. backup servers are not counted, and the method does not change them. The new server is that peer’s for every later request that the worker sends to the upstream, not only for the current request, until the worker exits or the configuration is reloaded; each worker keeps its own. An upstream with a zone is not supported: since 2.7.3 the method raises RuntimeError for one and leaves its server. Up to 2.7.2 it changed the server, and the change was not valid in the other workers (see “Not changed by this release” of the Nginx::Upstream#server= entry in the 2.7.2 release notes).

The string is an address and a port, read as nginx reads the address of a server directive: an IPv6 address goes in brackets, and unix: with a path names a UNIX-domain socket. The port is 80 when the string has none. A host name is resolved when the method is called, with the system resolver, and its first address is used; the worker serves no other client while it waits (see “What the operator’s code is responsible for” in the documentation), so give an IP address. The method raises TypeError when the argument is not a String (since 2.7.3), ArgumentError when the string is empty or 256 bytes or longer, and RuntimeError when nginx cannot read or resolve it; the server stays as it was then.

u = Nginx::Upstream.new "YOUR_UPSTREAM_NAME"
s = u.server #=> 127.0.0.1:80
u.server = "127.0.0.1:8080" #=> 127.0.0.1:8080

Sleeps in non-blocking way. It’s currently supported in the set, rewrite, access and content handlers. In a content handler (mruby_content_handler*) nginx waits for the handler since 2.7.3: the code after the sleep runs, and the request gets the response that the handler writes or the status that it returns. Up to 2.7.2 the request ended at the sleep without a response (see “Known limitations” in the 2.7.1 release notes). A content handler that runs in the location that Nginx.redirect runs from Ruby code still ends the request at the sleep, because the handler that called Nginx.redirect goes on after the call and may answer the request itself. After the sleep, Nginx::Async::HTTP.sub_request raises a RuntimeError in a content handler. In a log handler (mruby_log_handler, mruby_log_handler_code) and in the output filters (mruby_output_header_filter*, mruby_output_body_filter*), nginx cannot resume a handler that waits, so it raises a RuntimeError (since 2.7.1; in 2.7.0 a sleep in a log handler could crash the worker, and a sleep in a filter stopped the filter there and sent the response unfiltered). If the handler raises an exception after the call returns, the request gets 500 and the output of Nginx.rputs is not sent, unless the response was already started, for example by the location that Nginx.redirect ran. Then the 500 is not sent either. This holds since 2.7.1; in 2.7.0 the client got no response, the output of Nginx.rputs with status 200, or the status that the handler had set before the exception.

Nginx::Async.sleep 3000 # Sleep 3000 millisec

Nginx::Async::HTTP#sub_request(location, string_or_hash=nil)

Section titled “Nginx::Async::HTTP#sub_request(location, string_or_hash=nil)”

Sends a sub request in non-blocking way. It’s currently supported in the set, rewrite and access handlers. In a content handler that has waited in Nginx::Async.sleep, it raises a RuntimeError (since 2.7.3), because nginx would not finish the request after the subrequest. Like Nginx::Async.sleep, it raises a RuntimeError in a log handler and in the output filters (since 2.7.1; 2.7.0 started the subrequest there). If the handler raises an exception after the call returns, the request gets 500 and the output of Nginx.rputs is not sent, unless the response was already started, for example by the location that Nginx.redirect ran. Then the 500 is not sent either. This holds since 2.7.1, as for Nginx::Async.sleep.

Nginx::Async::HTTP.sub_request "/example", "q1=foo&q2=bar" # Send a sub request with the parameters
res = Nginx::Async::HTTP.last_response # Get the response of the sub request
Nginx.rputs res.body #=> "hello world"
Nginx.rputs res.headers #=> {"Date" => "Thu, 29 Nov 2018 07:55:22 GMT", ...}
Nginx.rputs res.status #=> 200

You can pass a hash instead of the string.

TODO: do we really need Utils.encode_parameters? It is called in sub_request(). Also is the following comment in test/conf/nginx.conf still true? “# BUG?: using Nginx::Utils.encode_parameters is sometimes missing call method for fiber_proc”

Nginx::Async::HTTP.sub_request "/example", Nginx::Utils.encode_parameters({q1: "foo", q2: "bar"})

Nginx::Async::last_response -> http_response

Section titled “Nginx::Async::last_response -> http_response”

Returns the response of the last sub request. See Nginx::Async::HTTP#sub_request for usage.

Response class returned from Nginx::Async::last_response. See Nginx::Async::HTTP#sub_request for usage.

Nginx::Async::HTTP::Response#body -> string

Section titled “Nginx::Async::HTTP::Response#body -> string”

Returns the response body of the last sub request. See Nginx::Async::HTTP#sub_request for usage.

Nginx::Async::HTTP::Response#headers -> hash

Section titled “Nginx::Async::HTTP::Response#headers -> hash”

Returns the response headers of the last sub request. See Nginx::Async::HTTP#sub_request for usage.

Nginx::Async::HTTP::Response#status -> integer

Section titled “Nginx::Async::HTTP::Response#status -> integer”

Returns the HTTP response status of the last sub request. See Nginx::Async::HTTP#sub_request for usage.

rack-based-api mrbgem provides RACK compatible APIs. You can write mruby code in the RACK way as below.

location /hello {
mruby_content_handler_code '
proc = Proc.new do |env|
[200, {"Content-Type" => "text/plain"}, ["hello ngx_mruby world!"]]
end
run proc
';
}

rack-based-api mrbgem adds run method to Kernel module. It takes care everything.

Send a call message to the obj.

The obj must respond to call. It takes one argument, the environment. It must return an array that contains the status, the headers and the body. See The RACK specification for more details.

class MyApp
def call(env)
status = 200
headers = {"Content-Type" => "text/plain", "X-NGX-MRUBY-INTERACTION-ID" => Uuid.uuid}
body = ["Got a request from " + env["REMOTE_ADDR"]]
[status, headers, body]
end
end
run MyApp.new

TODO: cleanup and add descriptions.

stream {
upstream dynamic_server0 {
server 127.0.0.1:58080;
}
server {
listen 12346;
mruby_stream_code '
c = Nginx::Stream::Connection.new "dynamic_server0"
c.upstream_server = "192.168.0.3:54321"
Nginx::Stream.log Nginx::Stream::LOG_NOTICE, "dynamic_server0 was changed to 192.168.0.3:54321"
';
proxy_pass dynamic_server0;
}
}

Create a listener on the specified IP address and the port in the hash.

Nginx::Stream.add_listener({address: "127.0.0.1:12350"})
Nginx::Stream.add_listener({address: "12351"})

See Nginx::Server#add_listener() for an example to create multiple listeners

The method works only in mruby_stream_server_context_code, while nginx reads the configuration. Anywhere else, for example in mruby_stream_code or mruby_stream_init_worker_code, it raises a RuntimeError (since 2.7.1).

Nginx::Stream.errlogger(log_level, string)

Section titled “Nginx::Stream.errlogger(log_level, string)”
Nginx::Stream.errlogger Nginx::Stream::LOG_NOTICE, "logging something"

Alias for Nginx::Stream.errlogger.

Returns the module name ngx_mruby-stream-module.

Nginx::Stream.module_name #=> "ngx_mruby-stream-module"

Log levels for Nginx::Stream.errlogger that mirror nginx error log levels. See Constants for log levels in the Nginx Class documentation for more details.

Name Description
Nginx::Stream::LOG_STDERR Defined in core/ngx_log.h, but it’s never used
Nginx::Stream::LOG_ALERT Emergency error log level
Nginx::Stream::LOG_EMERG Alert error log level
Nginx::Stream::LOG_CRIT Critical error log level
Nginx::Stream::LOG_ERR Error log level
Nginx::Stream::LOG_WARN Warning log level
Nginx::Stream::LOG_NOTICE Notice log level
Nginx::Stream::LOG_INFO Information log level
Nginx::Stream::LOG_DEBUG Debug log level

Return status for Nginx::Stream::Connection.stream_status.

Name Value
Nginx::Stream::OK 0
Nginx::Stream::ERROR -1
Nginx::Stream::AGAIN -2
Nginx::Stream::BUSY -3
Nginx::Stream::DONE -4
Nginx::Stream::DECLINED -5
Nginx::Stream::ABORT -6
  • example
stream {
upstream dynamic_server0 {
server 127.0.0.1:58080;
}
mruby_stream_init_code '
Userdata.new.new_upstream = "127.0.0.1:58081"
';
mruby_stream_init_worker_code '
p "ngx_mruby: STREAM: mruby_stream_init_worker_code"
';
mruby_stream_exit_worker_code '
p "ngx_mruby: STREAM: mruby_stream_exit_worker_code"
';
server {
listen 12346;
mruby_stream_code '
c = Nginx::Stream::Connection.new "dynamic_server0"
c.upstream_server = Userdata.new.new_upstream
';
proxy_pass dynamic_server0;
}
}

get the upstream configuration via upstream name

As for Nginx::Upstream.new, the string is the whole name of an upstream {} block of the stream {} block, compared case-insensitively; the method raises RuntimeError when no upstream has that name, and TypeError when the argument is not a String (since 2.7.3; up to 2.7.2 it also found an upstream whose name started with the argument).

# == nginx.conf ==
# upstream dynamic_server0 {
# server 127.0.0.1:58080;
# }
c = Nginx::Stream::Connection.new "dynamic_server0"
# == nginx.conf ==
# upstream dynamic_server0 {
# server 127.0.0.1:58080;
# }
c = Nginx::Stream::Connection.new "dynamic_server0"
c.upstream_server #=> "127.0.0.1:58080"

Nginx::Stream::Connection#upstream_server=

Section titled “Nginx::Stream::Connection#upstream_server=”

Sets the server of the upstream that Nginx::Stream::Connection.new named. As for Nginx::Upstream#server=, the servers of the upstream block that are not backup must have one address in all, and backup servers are not changed. The new server is that peer’s for every later session that the worker sends to the upstream, until the worker exits or the configuration is reloaded; each worker keeps its own. An upstream with a zone is not supported: since 2.7.3 the method raises RuntimeError for one and leaves its server.

The string is an IP address and a port, such as 127.0.0.1:12345 or [::1]:12345, or unix: with a path; host names are not resolved and raise. A string without a port is accepted, and the port is then 0. The method raises TypeError when the argument is not a String (since 2.7.3), and RuntimeError when the string is empty or 256 bytes or longer, or when nginx cannot read it as an address; the server stays as it was then.

# == nginx.conf ==
# upstream dynamic_server0 {
# server 127.0.0.1:58080;
# }
c = Nginx::Stream::Connection.new "dynamic_server0"
c.upstream_server #=> "127.0.0.1:58080"
c.upstream_server = "192.168.0.3:54321"

get the current stream status

if Nginx::Stream::Connection.remote_ip == "127.0.0.1"
current_status = Nginx::Stream::Connection.stream_status #=> Nginx::Stream::DECLINED
end
if Nginx::Stream::Connection.remote_ip == "127.0.0.1"
current_status = Nginx::Stream::Connection.stream_status #=> Nginx::Stream::DECLINED
Nginx::Stream::Connection.stream_status = Nginx::Stream::ABORT
Nginx::Stream.log Nginx::Stream::LOG_NOTICE, ¥
"current status=#{(current_status == Nginx::Stream::DECLINED) ? "NGX_DECLINED" : current_status} but deny from #{Nginx::Stream::Connection.remote_ip} return NGX_ABORT"
end
if Nginx::Stream::Connection.remote_ip == "127.0.0.1"
# something access control
end
  • access control example
stream {
server {
listen 12347;
mruby_stream_code '
if Nginx::Stream::Connection.remote_ip == "127.0.0.1"
current_status = Nginx::Stream::Connection.stream_status
Nginx::Stream::Connection.stream_status = Nginx::Stream::ABORT
Nginx::Stream.log Nginx::Stream::LOG_NOTICE, "current status=#{(current_status == Nginx::Stream::DECLINED) ? "NGX_DECLINED" : current_status} but deny from #{Nginx::Stream::Connection.remote_ip} return NGX_ABORT"
end
';
proxy_pass dynamic_server1;
}
}

Nginx::Stream::Connection.{remote_port,local_ip,local_addr,local_port,local_ip_port}

Section titled “Nginx::Stream::Connection.{remote_port,local_ip,local_addr,local_port,local_ip_port}”
server {
listen 127.0.0.1:12348;
mruby_stream_code '
Nginx::Stream.log Nginx::Stream::LOG_NOTICE, "local is #{Nginx::Stream::Connection.local_ip}:#{Nginx::Stream::Connection.local_port} remote_port is #{Nginx::Stream::Connection.remote_ip}:#{Nginx::Stream::Connection.remote_port}"
if Nginx::Stream::Connection.local_port != 12348 && Nginx::Stream::Connection.local_ip != "127.0.0.1"
Nginx::Stream::Connection.stream_status = Nginx::Stream::ABORT
end
';
proxy_pass static_server0;
}
server {
listen 127.0.0.1:12349;
mruby_stream_code '
Nginx::Stream.log Nginx::Stream::LOG_NOTICE, "local_ip_port is #{Nginx::Stream::Connection.local_ip_port}"
if Nginx::Stream::Connection.local_ip_port != "127.0.0.1:12349"
Nginx::Stream::Connection.stream_status = Nginx::Stream::ABORT
end
';
proxy_pass static_server0;
}

Do non-blocking sleep. It works in the code of mruby_stream and mruby_stream_code, which runs in the access phase of the stream session.

After the sleep, the session goes on as it does when the code does not sleep, by the result of the code: the next handler for Nginx::Stream::DECLINED (the default of Nginx::Stream::Connection.stream_status), the next phase for Nginx::Stream::OK, the wait of the session for Nginx::Stream::DONE and Nginx::Stream::AGAIN, and the end of the session for Nginx::Stream::ABORT or another status, and for an exception, which error.log records. This holds since 2.7.3; up to 2.7.2 a session whose code raised or set a status other than Nginx::Stream::DECLINED after the sleep was neither ended nor continued, and an exception after the sleep also aborted the next session.

# sleep 3000 millisec
Nginx::Stream::Async.sleep 3000