nginx match request body without using lua module

t5zmwmid  于 2023-05-16  发布在  Nginx
关注(0)|答案(1)|浏览(158)

在nginx中有没有一种方法可以根据请求体是否有字符串来做一些事情?我相信我可以用Lua模块来做。我想知道是否有一种方法可以单独使用nginx。
我希望下面这样的东西能起作用。

location /students-api {
    if ($request_body ~* "(.*)specialstudent(.*)" ) {
      set  $student_status  'special';
    }
  // and use student_status for some logic
 }
pod7payv

pod7payv1#

我认为它应该工作,但它需要测试。在实践中,我只使用$request_body进行日志记录,不确定它是否在请求处理的重写阶段可用。这里有一个官方的描述说:
当请求体被读取到内存缓冲区时,变量的值在proxy_passfastcgi_passuwsgi_passscgi_pass指令处理的位置可用。
此外,如果以后不使用这些捕获组,您不需要它们来检查变量是否存在子字符串(实际上,将它们保存在内存中只是浪费资源),只需if ($request_body ~* "specialstudent") { ... }就足够了。

更新

下面是另一种更有可能工作的方法,因为proxy_add_header指令肯定会在请求处理的重写阶段之后执行:

map $request_body $special {
    ~*"specialstudent"    "special";
    # otherwise '$special' variable value will be empty
}
server {
    ...
    location /students-api {
        ...
        proxy_set_header X-Student-Status $special;
        ...
    }
}

更新2

在测试了所有这些之后,我可以确认if方法不起作用:

server {
    ...
    location /students-api {
        if ($request_body ~* "specialstudent") {
            set $student_status "special";
        }
        proxy_set_header X-Student-Status $student_status;
        ...
    }
}

正如预期的那样,$request_body变量不会在请求处理的重写阶段初始化。但是,map方法可以按预期工作:

map $request_body $student_status {
    ~*"specialstudent"    "special";
    # otherwise '$special' variable value will be empty
}
server {
    ...
    location /students-api {
        proxy_set_header X-Student-Status $student_status;
        ...
    }
}

真正让我惊讶的是,下面的例子没有设置两个头中的任何一个:

map $request_body $student_status {
    ~*"specialstudent"    "special";
    # otherwise '$special' variable value will be empty
}
server {
    ...
    location /students-api {
        if ($request_body ~* "specialstudent") {
            set $student_special "special";
        }
        proxy_set_header X-Student-Status $student_status;
        proxy_set_header X-Student-Special $student_special;
        ...
    }
}

在请求处理的早期重写阶段访问$request_body变量会导致map转换也停止工作。我现在没有解释这种行为,如果有人能解释这里发生了什么,我会很感激。

更新3

我想我终于找到了解释Nginx教程中最后一个例子发生了什么的解释,这是由著名的lua-nginx-moduleOpenResty包的作者Yichun Zhang编写的:
一些Nginx变量选择在配置“get handler”时使用它们的值容器作为数据缓存。在此设置中,“获取处理程序”仅运行一次,即,在变量第一次被读取时,这减少了变量在其生命周期期间被多次读取时的开销。
如果在NGX_HTTP_REWRITE_PHASE早期访问$request_body变量,则看起来$request_body变量的行为完全相同(请参阅请求处理阶段描述)。如果在该阶段读取了它的值,则会将其缓存为空值,并在后续的请求处理阶段变得无用。

相关问题