14 Q& a One How to Handle Conflicts Arising From Lua Rules and Nginx Configuration Files

14 Q&A One- How to Handle Conflicts Arising from Lua Rules and NGINX Configuration Files #

Hello, I’m Wen Ming.

Up until now, in the Beginners section of the first module of the OpenResty column, we have covered all the material. Congratulations on staying committed and actively learning and practicing, and thank you for sharing your thoughts.

Many of the questions raised in the comments are very valuable, and I have already replied to most of them in the app. However, there are some questions that are more typical, interesting, or not convenient to reply to on mobile, which I have selected specifically for today’s Q&A, in order to address them collectively. On the other hand, this is also to ensure that no one misses any important points.

Let’s take a look at these 5 questions today.

Question 1: The name and language of OpenResty #

Q: Up until now, I still haven’t understood the origin of the name OpenResty. Additionally, OpenResty utilizes the Lua language and adds wings to it. So why not utilize other scripting languages like Shell?

A: In fact, OpenResty was originally a project of Yahoo China, which started in October 2007. At that time, there was a wave of OpenAPI, so agentzh (the creator) wanted to create something similar that could support various Web Service needs. The name “Open” came from OpenAPI, while “Resty” came from “rest API”. Initially, the purpose of OpenResty was not to be a web server and development platform, but rather to be an application like a website.

When OpenResty was open-sourced more than ten years ago, support for synchronous non-blocking languages was scarce. Even now, there are not many backend languages that can achieve the performance level of OpenResty. Currently, more developers choose to use OpenResty in the fields of API gateways and software WAFs, which can be considered as a natural choice for developers.

As for the language, OpenResty is not the only project that embeds other development languages into NGINX. For example, the NGINX official team embedded JavaScript, and there are also other open-source projects that embed PHP into NGINX.

Usually, the choice of which language to use takes into account multiple factors such as coroutines, JIT, and language popularity. For OpenResty, Lua was indeed the best choice back in 2007. In fact, in the earliest versions of OpenResty, perl was chosen instead of Lua, which can be seen as taking a detour.

Question 2: Rule Priority in Configuration Files #

Q: When there is a conflict between Lua rules in OpenResty and the NGINX configuration file, for example, when NGINX has a rewrite rule and also references rewrite_by_lua_file, what is the priority of these two rules?

A: Actually, it depends on how the rewrite rule in the NGINX configuration is written, whether it is “break” or “last”. This is stated in the official documentation of OpenResty and there is an example code provided:

location /foo {
    rewrite ^ /bar;
    rewrite_by_lua 'ngx.exit(503)';
}
location /bar {
    ...
}

In this example configuration, ngx.exit(503) will not be executed.

However, if you change it to the following format, ngx.exit(503) can be executed:

rewrite ^ /bar break;

Nevertheless, to avoid ambiguity, I recommend using OpenResty to handle the rewrite instead of NGINX’s configuration. To be honest, many of NGINX’s configurations are relatively obscure and you need to repeatedly refer to the documentation to understand them.

Question 3: Why is my code reporting an error? #

Q: Why do these two lines of code, when executed with LuaJIT, both report an error “module not found”? I am using LuaJIT version 2.0.5.

local new_tab = require('table.new')
-- Or
require('table.clear')

Executing these lines will result in the following error message:

luajit: table_luajit.lua:1: module 'table.new' not found:

A: This issue is worth noting. These two lines of code require LuaJIT version 2.1 to run. The documentation can be found here: https://github.com/LuaJIT/LuaJIT/blob/v2.1/doc/extensions.html#L218. You can learn more about it there.

In fact, this is something you should pay special attention to when using OpenResty. OpenResty requires a specific version of LuaJIT to work properly, as we mentioned before. OpenResty is based on the LuaJIT 2.1 branch and has made many of its own extensions to LuaJIT.

Therefore, when running the code in this column, please remember to use OpenResty’s official installation method. If you compile it by adding the lua-nginx-module on top of NGINX, you will still encounter various difficulties.

Question 4: Confusion about null values #

Q: I have encountered some confusing things related to ngx.null, nil, null, and "". When searching online, I found that some people say that null is a definition of ngx.null. When dealing with the return results of Redis, it is often necessary to check if the result is empty. In this case, which value should we compare it with? Are there any other pitfalls related to these values? I have never had a clear understanding of this, so I would like to confirm with the teacher.

A: Before answering your question, I suggest that you use the following code in lua-resty-redis to find a key:

local res, err = red:get("dog")

If the return value res is nil, it means that the function call failed; if res is ngx.null, it means that the key “dog” doesn’t exist in Redis. This is because Lua’s nil cannot be used as a value in a table, so OpenResty introduced ngx.null as an empty value in the table.

You can print out ngx.null and its type using the following code:

# Print ngx.null
$ resty -e 'print(ngx.null)'
null

# Print the type
$ resty -e 'print(type(ngx.null))'
userdata

As you can see, ngx.null is not equal to nil, it is of type userdata.

Furthermore, in OpenResty, there are many types of null values, such as cjson.null, cdata:NULL, etc. I will talk about them specifically later.

In summary, in OpenResty, only nil and false are considered as false values. So, when writing code like if not res then, you need to be very cautious. It is better to use a clear expression like if res ~= nil and res ~= false and make sure to have corresponding test cases to cover it.

Question 5: What is an API Gateway? #

Q: What exactly is the API Gateway mentioned in the article? And what is the difference compared to web servers like NGINX, Tomcat, and Apache?

A: The API Gateway is actually a gateway used to manage services in a unified manner. For example, services like payment and user login are all provided externally in the form of APIs, and they all require a gateway to achieve unified security and identity authentication.

The API Gateway can replace traditional NGINX and Apache to handle north-south traffic, and it can also handle east-west traffic in a microservices environment. It is a middleware that is more closely related to business, rather than a low-level web server.

Therefore, in the last few articles of this column, I will show you how to implement an API Gateway. This is currently one of the hottest use cases for OpenResty.

Learning is a process that requires repeated and deliberate practice, just like when you were in high school or university. It is important to ask questions and be willing to ask questions as it is an important step in absorbing knowledge. I hope you can experience the process of “reading the thick book and then reading the thin book” in your learning journey.

Finally, feel free to write down your questions in the comments section. I will continue to answer them. I hope to help you transform what you have learned into knowledge through communication and Q&A. You are also welcome to share this article with your colleagues and friends to exchange ideas and progress together.