4
ngx_lua - Embed the Power of Lua into Nginx
9
This module is still under active development but is already production
12
Commit bit can be freely delivered at your request ;)
17
# set search paths for pure Lua external libraries (';;' is the default path):
18
lua_package_path '/foo/bar/?.lua;/blah/?.lua;;';
20
# set search paths for Lua external libraries written in C (can also use ';;'):
21
lua_package_cpath '/bar/baz/?.so;/blah/blah/?.so;;';
24
location /inline_concat {
25
# MIME type determined by default_type:
26
default_type 'text/plain';
31
set_by_lua $res "return ngx.arg[1]..ngx.arg[2]" $a $b;
35
location /rel_file_concat {
38
# script path relative to nginx prefix
39
# $ngx_prefix/conf/concat.lua contents:
41
# return ngx.arg[1]..ngx.arg[2]
43
set_by_lua_file $res conf/concat.lua $a $b;
47
location /abs_file_concat {
50
# absolute script path not modified
51
set_by_lua_file $res /usr/nginx/conf/concat.lua $a $b;
55
location /lua_content {
56
# MIME type determined by default_type:
57
default_type 'text/plain';
59
content_by_lua "ngx.say('Hello,world!')"
63
# MIME type determined by default_type:
64
default_type 'text/plain';
66
# try access /nginx_var?a=hello,world
67
content_by_lua "ngx.print(ngx.var['arg_a'], '\\n')";
70
location /request_body {
71
# force reading request body (default off)
72
lua_need_request_body on;
74
content_by_lua 'ngx.print(ngx.var.request_body)';
77
# transparent non-blocking I/O in Lua via subrequests
79
# MIME type determined by default_type:
80
default_type 'text/plain';
83
local res = ngx.location.capture("/some_other_location")
84
if res.status == 200 then
91
# MIME type determined by default_type:
92
default_type 'text/plain';
95
local num = tonumber(ngx.var.arg_num) or 0
96
ngx.say("num is: ", num)
99
res = ngx.location.capture("/recur?num=" .. tostring(num - 1))
100
ngx.print("status=", res.status, " ")
101
ngx.print("body=", res.body)
112
This module embeds the Lua interpreter into the nginx core and integrates the powerful Lua threads (aka Lua coroutines) into the nginx event model
113
by means of nginx subrequests.
115
Unlike Apache's mod_lua and Lighttpd's mod_magnet, Lua code written atop this module can be 100% non-blocking on network traffic
116
as long as you use the `ngx.location.capture` interface
117
to let the nginx core do all your
118
requests to mysql, postgresql, memcached,
119
upstream http web services, and etc etc etc (see
120
ngx_drizzle, ngx_postgres, ngx_memc, and ngx_proxy modules for details).
122
The Lua interpreter instance is shared across all
123
the requests in a single nginx worker process.
125
Request contexts are isolated from each other
126
by means of Lua (lightweight) threads (aka Lua coroutines).
127
And Lua modules loaded are persistent on
128
the nginx worker process level. So the memory
129
footprint is quite small even when your
130
nginx worker process is handling 10K requests at the same time.
132
We're already using this module very heavily
133
in our production web applications here in
134
Taobao.com, Alibaba Group.
142
* **Syntax:** `lua_package_path <lua-style-path-str>`
143
* **Default:** The content of LUA_PATH environ variable or Lua's compiled-in
145
* **Context:** `main`
147
Set the Lua module searching path used by scripts specified by `set_by_lua*`
148
and `content_by_lua*`. The path string is in standard Lua path form, and `;;`
149
can be used to stand for the original path.
154
* **Syntax:** `lua_package_cpath <lua-style-cpath-str>`
155
* **Default:** The content of LUA_CPATH environ variable or Lua's compiled-in
157
* **Context:** `main`
159
Set the Lua C-module searching path used by scripts specified by `set_by_lua*`
160
and `content_by_lua*`. The cpath string is in standard Lua cpath form, and `;;`
161
can be used to stand for the original cpath.
166
* **Syntax:** `set_by_lua $res <lua-script-str> [$arg1 $arg2 ...]`
167
* **Context:** `main | server | location | sif | lif`
169
Execute user code specified by `<lua-script-str>` with input arguments `$arg1
170
$arg2 ...`, and set the script's return value to `$res` in string form. In
171
`<lua-script-str>` code the input arguments can be retrieved from `ngx.arg`
172
table (index starts from `1` and increased sequentially).
174
`set_by_lua*` directives are designed to execute small and quick codes. Nginx
175
event loop is blocked during the code execution, so you'd better **NOT** call
176
anything that may be blocked or time-costy.
178
Note that `set_by_lua` can only output a value to a single nginx variable at
179
a time. But a work-around is also available by means of the ngx.var.xxx interface,
183
set $diff ''; # we have to predefine the $diff variable here
189
ngx.var.diff = a - b; -- write to $diff directly
190
return a + b; -- return the $sum value normally
193
echo "sum = $sum, diff = $diff";
199
* **Syntax:** `set_by_lua_file $res <path-to-lua-script> [$arg1 $arg2 ...]`
200
* **Context:** `main | server | location | sif | lif`
202
Basically the same as `set_by_lua`, except the code to be executed is in the
203
file specified by `<path-lua-script>`.
205
The user code is loaded once at the first request and cached. Nginx config must
206
be reloaded if you modified the file and expected to see updated behavior.
211
* **Syntax:** `content_by_lua <lua-script-str>`
212
* **Context:** `location | lif`
214
Act as a content handler and execute user code specified by `<lua-script-str>`
215
for every request. The user code may call predefined APIs to generate response
218
The use code is executed in a new spawned coroutine with independent globals
219
environment (i.e. a sandbox). I/O operations in user code should only be done
220
through predefined Nginx APIs, otherwise Nginx event loop may be blocked and
221
performance may drop off dramatically.
223
As predefined Nginx I/O APIs used coroutine yielding/resuming mechanism, the
224
user code should not call any modules that used coroutine API to prevent
225
obfuscating the predefined Nginx APIs (actually coroutine module is masked off
226
in `content_by_lua*` directives). This limitation is a little crucial, but
227
don't worry! We're working on a alternative coroutine implementation that can
228
be fit in the Nginx event framework. When it is done, the user code will be
229
able to use coroutine mechanism freely as in standard Lua again!
234
* **Syntax:** `content_by_lua_file <path-to-lua-script>`
235
* **Context:** `location | lif`
237
Basically the same as `content_by_lua`, except the code to be executed is in
238
the file specified by `<path-lua-script>`.
240
The user code is loaded once at the first request and cached. Nginx config must
241
be reloaded if you modified the file and expected to see updated behavior.
243
lua_need_request_body
244
---------------------
246
* **Syntax:** `lua_need_request_body <on | off>`
248
* **Context:** `main | server | location`
250
Force reading request body data or not. The request data won't be read into
251
$request_body Nginx variable by default, so you have to explicitly force
252
reading the body if you need its content.
260
Index the input arguments to the set_by_lua* directive:
271
'return tonumber(ngx.arg[1]) + tonumber(ngx.arg[2])'
277
that outputs 88, the sum of 32 and 56.
279
This is only available in set_by_lua* directives.
281
Read and write Nginx variables
282
------------------------------
284
value = ngx.var.some_nginx_variable_name
285
ngx.var.some_nginx_variable_name = value
287
Note that you can only write to nginx variables that are already defined.
291
set $my_var ''; # this line is required to create $my_var at config time
293
ngx.var.my_var = 123;
298
That is, nginx variables cannot be created on-the-fly.
300
This is available in both set_by_lua* and content_by_lua*
303
---------------------
310
HTTP method constants
311
---------------------
314
value = ngx.HTTP_HEAD
316
value = ngx.HTTP_POST
317
value = ngx.HTTP_DELETE
319
HTTP status constants
320
---------------------
323
value = ngx.HTTP_CREATED
324
value = ngx.HTTP_MOVED_PERMANENTLY
325
value = ngx.HTTP_MOVED_TEMPORARILY
326
value = ngx.HTTP_NOT_MODIFIED
327
value = ngx.HTTP_BAD_REQUEST
328
value = ngx.HTTP_GONE
329
value = ngx.HTTP_NOT_FOUND
330
value = ngx.HTTP_NOT_ALLOWED
331
value = ngx.HTTP_FORBIDDEN
332
value = ngx.HTTP_INTERNAL_SERVER_ERROR
333
value = ngx.HTTP_SERVICE_UNAVAILABLE
335
Nginx log level constants
336
-------------------------
338
log_level = ngx.STDERR
339
log_level = ngx.EMERG
340
log_level = ngx.ALERT
344
log_level = ngx.NOTICE
346
log_level = ngx.DEBUG
351
Emit args concatenated to `error.log`, with log level `ngx.NOTICE` and prefix `lua print: `.
355
ngx.log(ngx.NOTICE, 'lua print: ', a, b, ...)
357
Nil arguments are accepted and result in literal "nil".
359
ngx.location.capture(uri, options?)
360
-----------------------------------
362
Issue a synchronous but still non-blocking "nginx subrequest" using `uri`.
364
Nginx subrequests provide a powerful way to make
365
non-blocking internal requests to other locations
366
configured with disk file directory or *any*
367
other nginx C modules like
368
`ngx_proxy`, `ngx_fastcgi`, `ngx_memc`,
370
`ngx_drizzle`, and even `ngx_lua` itself and etc etc etc.
372
Also note that subrequests just mimic the HTTP
373
interface but there's *no*
374
extra HTTP/TCP traffic *nor* IPC involved. Everything
375
works internally, efficiently, on the C level.
377
Subrequests are completely different from HTTP 301/302 redirection (via `ngx.redirect()`) and internal redirection (via `ngx.exec()`).
379
Here's a basic example:
381
res = ngx.location.capture(uri)
383
Returns a Lua table with three slots (`res.status`, `res.header`, and `res.body`).
385
`res.header` holds all the response headers of the
386
subrequest and it is a normal Lua table.
388
URI query strings can be concatenated to URI itself, for instance,
390
res = ngx.location.capture('/foo/bar?a=3&b=4')
392
Named locations like `@foo` are not allowed due to a limitation in
393
the nginx core. Use normal locations combined with the `internal` directive to
394
prepare internal-only locations.
396
An optional option table can be fed as the second
397
argument, which support various options like
398
`method`, `body`, `args`, and `share_all_vars`.
399
Issuing a POST subrequest, for example,
400
can be done as follows
402
res = ngx.location.capture(
404
{ method = ngx.HTTP_POST, body = 'hello, world' }
407
See HTTP method constants methods other than POST.
408
The `method` option is `ngx.HTTP_GET` by default.
410
The `share_all_vars` option can control whether to share nginx variables
411
among the current request and the new subrequest. If this option is set to `true`, then
412
the subrequest can see all the variable values of the current request while the current
413
requeset can also see any variable value changes made by the subrequest.
414
Note that variable sharing can have unexpected side-effects
415
and lead to confusing issues, use it with special
416
care. So, by default, the option is set to `false`.
418
The `args` option can specify extra url arguments, for instance,
420
ngx.location.capture('/foo?a=1',
421
{ args = { b = 3, c = ':' } }
426
ngx.location.capture('/foo?a=1&b=3&c=%3a')
428
that is, this method will autmotically escape argument keys and values according to URI rules and
429
concatenating them together into a complete query string. Because it's all done in hand-written C,
430
it should be faster than your own Lua code.
432
The `args` option can also take plain query string:
434
ngx.location.capture('/foo?a=1',
435
{ args = 'b=3&c=%3a' } }
438
This is functionally identical to the previous examples.
440
This function is only available in `content_by_lua` and `content_by_lua_file`.
445
Read and write the response status. This should be called
446
before sending out the response headers.
448
ngx.status = ngx.HTTP_CREATED
451
This function is only available in `content_by_lua` and `content_by_lua_file`.
454
-----------------------
456
Set/add/clear response headers. Underscores (_) in the header names will be replaced by dashes (-) and the header names will be matched case-insentively.
458
-- equivalent to ngx.header["Content-Type"] = 'text/plain'
459
ngx.header.content_type = 'text/plain';
461
ngx.header["X-My-Header"] = 'blah blah';
463
Multi-value headers can be set this way:
465
ngx.header['Set-Cookie'] = {'a=32; path=/', 'b=4; path=/'}
469
Set-Cookie: a=32; path=/
470
Set-Cookie: b=4; path=/
472
in the response headers. Only array-like tables are accepted.
474
Note that, for those standard headers that only accepts a single value, like Content-Type, only the last element
475
in the (array) table will take effect. So
477
ngx.header.content_type = {'a', 'b'}
481
ngx.header.content_type = 'b'
483
Setting a slot to nil effectively removes it from the response headers:
485
ngx.header["X-My-Header"] = nil;
487
same does assigning an empty table:
489
ngx.header["X-My-Header"] = {};
491
`ngx.header` is not a normal Lua table so you cannot
494
Reading values from ngx.header.HEADER is not implemented yet.
496
This function is only available in `content_by_lua` and `content_by_lua_file`.
501
Does an internal redirect to uri with args.
503
ngx.exec('/some-location');
504
ngx.exec('/some-location', 'a=3&b=5&c=6');
505
ngx.exec('/some-location?a=3&b=5', 'c=6');
507
Named locations are also supported, but query strings are ignored. For example
519
Note that this is very different from ngx.redirect() in that
520
it's just an internal redirect and no new HTTP traffic is involved.
522
This method never returns.
524
This method MUST be called before `ngx.send_headers()` or explicit response body
525
outputs by either `ngx.print` or `ngx.say`.
527
This method is very much like the `echo_exec`
528
directive in the ngx_echo module.
530
This function is only available in `content_by_lua` and `content_by_lua_file`.
532
ngx.redirect(uri, status?)
533
--------------------------
535
Issue an HTTP 301 or 302 redirection to `uri`.
537
The optional `status` parameter specify whether
538
301 or 302 to be used. It's 302 (ngx.HTTP_MOVED_TEMPORARILY) by default.
540
Here's a small example:
542
return ngx.redirect("/foo")
544
which is equivalent to
546
return ngx.redirect("http://localhost:1984/foo", ngx.HTTP_MOVED_TEMPORARILY)
548
assuming the current server name is `localhost` and it's listening on the `1984` port.
550
This method MUST be called before `ngx.send_headers()` or explicit response body
551
outputs by either `ngx.print` or `ngx.say`.
553
This method never returns.
555
This method is very much like the `rewrite` directive with the `redirect` modifier in the standard
556
`ngx_rewrite` module, for example, this nginx.conf snippet
558
rewrite ^ /foo redirect; # nginx config
560
is equivalent to the following Lua code
562
return ngx.redirect('/foo'); -- lua code
566
rewrite ^ /foo permanent; # nginx config
570
return ngx.redirect('/foo', ngx.HTTP_MOVED_PERMANENTLY) -- Lua code
572
This function is only available in `content_by_lua` and `content_by_lua_file`.
577
Explicitly send out the response headers.
579
Usually you don't have to send headers yourself. ngx_lua
580
will automatically send out headers right before you
581
output contents via `ngx.say` or `ngx.print`.
583
Headers will also be sent automatically when `content_by_lua` exits normally.
585
This function is only available in `content_by_lua` and `content_by_lua_file`.
590
Emit args concatenated to the HTTP client (as response body).
592
Nil arguments are not allowed.
594
This function is only available in `content_by_lua` and `content_by_lua_file`.
599
Just as `ngx.print` but also emit a trailing newline.
601
Nil arguments are not allowed.
603
This function is only available in `content_by_lua` and `content_by_lua_file`.
605
ngx.log(log_level, ...)
606
-----------------------
608
Log args concatenated to error.log with the given logging level.
610
Nil arguments are accepted and result in literal "nil".
612
This function is only available in `content_by_lua` and `content_by_lua_file`.
617
Force flushing the response outputs.
619
This function is only available in `content_by_lua` and `content_by_lua_file`.
624
Interrupts the execution of the current Lua thread and returns
625
status code to nginx.
627
The `status` argument can be `ngx.OK`, `ngx.ERROR`, `ngx.HTTP_NOT_FOUND`,
628
`ngx.HTTP_MOVED_TEMPORARILY`,
629
or other HTTP status numbers.
631
This function is only available in `content_by_lua` and `content_by_lua_file`.
636
Explicitly specify the end of the response output stream.
638
This function is only available in `content_by_lua` and `content_by_lua_file`.
643
Escape `str` as a URI component.
645
newstr = ngx.escape_uri(str)
647
ngx.unescape_uri(str)
648
---------------------
650
Unescape `str` as a escaped URI component.
652
newstr = ngx.unescape_uri(str)
654
ngx.encode_base64(str)
655
----------------------
657
Encode `str` to a base64 digest
659
newstr = ngx.encode_base64(str)
661
ngx.decode_base64(str)
662
----------------------
664
Decode `str` as a base64 digest to the raw form
666
newstr = ngx.decode_base64(str)
670
Returns today's date (in the format `yyyy-mm-dd`) from nginx cached time (no syscall involved unlike Lua's date library).
673
This is the local time.
677
Returns the elapsed seconds from the epoch for the current timestamp from the nginx cached time (no syscall involved unlike Lua's date library).
681
Returns the current timestamp (in the format `yyyy-mm-dd hh:mm:ss`) of the nginx cached time (no syscall involved unlike Lua's date library).
683
This is the local time.
688
Returns the current timestamp (in the format `yyyy-mm-dd hh:mm:ss`) of the nginx cached time (no syscall involved unlike Lua's date library).
690
This is the UTC time.
694
Returns a formated string can be used as the cookie expiration time. The parameter `sec` is the timestamp in seconds (like those returned from `ngx.time`).
696
ngx.say(ngx.cookie_time(1290079655))
697
-- yields "Thu, 18-Nov-10 11:27:35 GMT"
699
ndk.set_var.DIRECTIVE
700
---------------------
702
This mechanism allows calling other nginx C modules' directives that are
703
implemented by Nginx Devel Kit (NDK)'s set_var submodule's ndk_set_var_value.
705
For example, ngx_set_misc module's set_escape_uri, set_quote_sql_str, and etc.
709
local res = ndk.set_var.set_escape_uri('a/b');
710
-- now res == 'a%2fb'
715
The Lua state (aka the Lua vm instance) is shared across all the requests
716
handled by a single nginx worker process to miminize memory use.
718
On a ThinkPad T400 2.80 GHz laptop, it's easy to achieve 25k req/sec using ab
719
w/o keepalive and 37k+ req/sec with keepalive.
721
You can get better performance when building this module
727
1. Install lua into your system. At least Lua 5.1 is required.
728
Lua can be obtained freely from its project [homepage](http://www.lua.org/).
730
1. Download the latest version of the release tarball of this module from
731
lua-nginx-module [file list](http://github.com/chaoslawful/lua-nginx-module/downloads).
733
1. Grab the nginx source code from [nginx.net](http://nginx.net/), for example,
734
the version 0.8.53 (see nginx compatibility), and then build the source with
737
$ wget 'http://sysoev.ru/nginx/nginx-0.8.53.tar.gz'
738
$ tar -xzvf nginx-0.8.53.tar.gz
741
# tell nginx's build system where to find lua:
742
export LUA_LIB=/path/to/lua/lib
743
export LUA_INC=/path/to/lua/include
745
# or tell where to find LuaJIT when you want to use JIT instead
746
# export LUAJIT_LIB=/path/to/luajit/lib
747
# export LUAJIT_INC=/path/to/luajit/include/luajit-2.0
749
# Here we assume you would install you nginx under /opt/nginx/.
750
$ ./configure --prefix=/opt/nginx \
751
--add-module=/path/to/ndk_devel_kit \
752
--add-module=/path/to/lua-nginx-module
760
The following versions of Nginx should work with this module:
762
* 0.8.x (last tested: 0.8.53)
763
* 0.7.x >= 0.7.46 (last tested: 0.7.67)
765
Earlier versions of Nginx like 0.6.x and 0.5.x will **not** work.
767
If you find that any particular version of Nginx above 0.7.44 does not
768
work with this module, please consider reporting a bug.
773
To run the test suite, you also need the following perl and nginx modules:
776
* test-nginx: <http://github.com/agentzh/test-nginx>
779
* echo-nginx-module: <http://github.com/agentzh/echo-nginx-module>
780
* drizzle-nginx-module: <http://github.com/chaoslawful/drizzle-nginx-module>
781
* rds-json-nginx-module: <http://github.com/agentzh/rds-json-nginx-module>
782
* set-misc-nginx-module: <http://github.com/agentzh/set-misc-nginx-module>
783
* memc-nginx-module: <http://github.com/agentzh/memc-nginx-module>
784
* srcache-nginx-module: <http://github.com/agentzh/srcache-nginx-module>
785
* ngx_auth_request: <http://mdounin.ru/hg/ngx_http_auth_request_module/>
787
These module's adding order is IMPORTANT! For filter modules's position in
788
filtering chain affects a lot. The correct configure adding order is:
791
2. set-misc-nginx-module
792
3. ngx_http_auth_request_module
795
6. lua-nginx-module (i.e. this module)
796
7. srcache-nginx-module
797
8. drizzle-nginx-module
798
9. rds-json-nginx-module
803
* Add directives to run lua codes when nginx stops/reloads.
804
* Add `ngx.location.capture_multi` to allow multiple parallel subrequests.
805
* Deal with TCP 3-second delay problem under great connection harness.
806
* Add `lua_code_cache on|off` directive to allow .lua files updated on-the-fly during development.
811
* Add 'lua_require' directive to load module into main thread's globals
812
* Add Lua VM passive yield and resume (using debug hook)
813
* Make set_by_lua using the same mechanism as content_by_lua
818
* **WATCH OUT: Globals WON'T persist between requests**, because of the one-coroutine-per-request
819
isolation design. Especially watch yourself when using `require()` to import modules, and
822
local xxx = require('xxx')
824
instead of the old deprecated form:
828
The old form will cause module unusable in requests for the reason told
829
previously. If you have to stick with the old form, you can always force
830
loading module for every request by clean `package.loaded.<module>`, like this:
832
package.loaded.xxx = nil
838
* "Introduction to ngx_lua" ( <https://github.com/chaoslawful/lua-nginx-module/wiki/Introduction> )
839
* ngx_devel_kit ( <http://github.com/simpl-it/ngx_devel_kit> )
840
* echo-nginx-module ( <http://github.com/agentzh/echo-nginx-module> )
841
* drizzle-nginx-module ( <http://github.com/chaoslawful/drizzle-nginx-module> )
842
* postgres-nginx-module ( <http://github.com/FRiCKLE/ngx_postgres> )
843
* memc-nginx-module ( <http://github.com/agentzh/memc-nginx-module> )
844
* ngx_http_js_module ( <http://github.com/kung-fu-tzu/ngx_http_js_module> )
849
* chaoslawful (王晓哲) <chaoslawful at gmail dot com>
850
* agentzh (章亦春) <agentzh at gmail dot com>
855
This module is licenced under the BSD license.
857
Copyright (C) 2009, Taobao Inc., Alibaba Group ( http://www.taobao.com ).
859
Copyright (C) 2009 by Xiaozhe Wang (chaoslawful) <chaoslawful@gmail.com>.
861
Copyright (C) 2009 by Yichun Zhang (agentzh) <agentzh@gmail.com>.
865
Redistribution and use in source and binary forms, with or without
866
modification, are permitted provided that the following conditions
869
* Redistributions of source code must retain the above copyright
870
notice, this list of conditions and the following disclaimer.
872
* Redistributions in binary form must reproduce the above copyright
873
notice, this list of conditions and the following disclaimer in the
874
documentation and/or other materials provided with the distribution.
876
* Neither the name of the Taobao Inc. nor the names of its
877
contributors may be used to endorse or promote products derived from
878
this software without specific prior written permission.
880
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
881
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
882
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
883
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
884
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
885
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
886
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
887
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
888
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
889
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
890
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.