【问题标题】:Is it possible to rewrite SOAP POST request bodies with Apache or Nginx?是否可以使用 Apache 或 Nginx 重写 SOAP POST 请求主体?
【发布时间】:2019-05-05 15:07:09
【问题描述】:

我正在尝试重写 SOAP POST 请求 body 和 header,以便 Apache 或 Nginx可以将其代理到驻留在另一台服务器上的应用程序。

请求是这样组成的,这个特别是指“UploadDocument_v4”功能:

POST / HTTP/1.1
Accept-Encoding: gzip, deflate
Content-Type: application/soap+xml;charset=UTF-8;action="http://server.workstepController.Process/UploadDocument_v4"
Host: 192.168.1.2
Content-Length: 245508
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
Connection: close

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:com="http://server.workstepController.Process/">
   <soap:Header/>
   <soap:Body>
      <com:UploadDocument_v4>
         <!--Optional:-->
         <com:workstepId></com:workstepId>
         <!--Optional:-->
         <com:customizationId></com:customizationId>
         <!--Optional:-->
         <com:document>OMISSIS</com:document>
         <!--Optional:-->
         <com:fileName>contract.pdf</com:fileName>
         <com:timeToLive>100</com:timeToLive>
         <!--Optional:-->
         <com:transactionInformation><![CDATA[
         <!--Further information for this transaction.-->
                              <TransactionInformation>
                                <!--The client id.-->
                                <ClientId>myClientId</ClientId>
                                <!--The transaction id.-->
                                <TransactionId>1234567890</TransactionId>
                                <!--Specifies if the currentWorkstepInformation should be returned by the method.-->
                                <ReturnWorkstepInfo>1</ReturnWorkstepInfo>
                                <!--The product name.-->
                                <ProductName />
                                <!--The product version.-->
                                <ProductVersion />
                                <!--The product release date in format YYYY-MM-DD.-->
                                <ProductReleaseDate />
                                <!--The email of the user.-->
                                <UserId />
                                <!--The ip address of the user.-->
                                <IpAddress />
                              </TransactionInformation>
         ]]></com:transactionInformation>
      </com:UploadDocument_v4>
   </soap:Body>
</soap:Envelope>

我需要做的是重写这个请求,以便它调用相同的函数,但使用 _v2 版本。因此,所有对 _v4 的引用都应在 body AND header 中替换为 _v2。

这有可能吗?到目前为止,我一直在使用 Nginx 和 Apache,但是如果可能的话,我还没有找到相关的模块。

感谢您提供的任何见解。

更新: 正如 Ivan 在 cmets 中建议的那样,我尝试安装 Openresty,并且通过使用基本配置,我能够确定它正在工作。但是,我似乎无法弄清楚如何替换正文和标题。 nginx.conf 文件如下:

worker_processes 1;
error_log logs/error.log
events{
   worker_connections 1024;
}

http{
     server{
        listen 8080;
        location / {
            --default_type text/html;
                rewrite_by_lua_block{
                --This is not being substituted
                ngx.req.set_header("Content-Type", "[...]/UploadDocument_v2")
                };
            a = ngx.req.read_body();
            a = string.gsub(a,"_v4","_v2");

            return 302 http://192.168.1.3:1234;
         }
    }
}

【问题讨论】:

  • 我认为这可以通过openresty 或ngx_http_lua_module 完成。另请参阅this 问题。
  • 您好伊万,感谢您的回复。这也适用于请求标头吗?谢谢
  • 据我所知,对于请求标头的操作,有 ngx.req.get_headers 和 ngx.req.set_header 方法。
  • 您好 Ivan,我已尝试配置这些模块,并且它们似乎已正确安装。但是,我似乎无法执行字符串的简单替换。另外,不幸的是,标头指令不会覆盖任何内容。我会用配置更新问题。

标签: apache http nginx soap lua


【解决方案1】:

好吧,距离我用 Lua 写东西已经过去了大约两年,但我会尝试 :)

    location / {
        access_by_lua '
            ngx.req.read_body()
            local body = ngx.req.get_body_data()
            body = string.gsub(body, "_v4", "_v2")
            ngx.req.set_body_data(body)
            local header = ngx.req.get_headers()["Content-Type"]
            header = string.gsub(header, "_v4", "_v2")
            ngx.req.set_header("Content-Type", header)
        ';
        proxy_pass http://192.168.1.3:1234;
    }

我使用curl 和 PHP 脚本测试了这个配置,它打印 HTTP 标头和 POST 请求正文,它可以工作。您不能使用 return 302 ...,因为您的 HTTP 标头将针对新请求重新生成,您必须改用 proxy_pass 指令。请注意,如果您通过域而不是 IP 地址指定代理服务器,则必须使用 proxy_set_header Host proxy-domain.com 指令,可能还有 resolver 指令。

【讨论】:

  • 嗨,Ivan,非常感谢您的剧本,它确实为我指明了正确的方向。当我尝试运行 SOAP 查询时,错误日志包含以下内容:“client_body_temp/00000000005 failed (13:permission denied)”。你过去有没有发生过这个错误?我尝试了一些 Google-Fu,但至今无济于事。我想这是对此类文件夹的权限问题,但是使用 chmod/chown,我似乎无法弄清楚。再次感谢您提供任何见解
  • 不,这个错误从来没有发生在我身上,但它肯定与权限有关。错误日志中client_body_temp 目录的完整路径是什么?这个目录存在吗?它有什么权限,它的owner 和group 属性是什么?在哪个用户下运行 openresty 工作进程? (ps aux|grep nginx) 你启用 SELinux 了吗?
  • 嗨,Ivan,完整的错误如下:2018/12/06 15:04:04 [crit] 1607#1607: *4 open() "/root/work/client_body_temp/0000000004" failed (13: Permission denied)。该目录存在并且是在测试脚本时创建的。我尝试将权限更改为用户:nginx.nginx,nobody.nobody,但结果似乎是相同的错误。主进程以 root 身份运行,但工作进程以“nobody”用户身份运行。 SELinux 已启用,但使用 setenforce 0 禁用它并不会改变这种情况。
  • chmod 777 client_body_temp 不改变情况? (在我们没有找到问题根源的情况下保持禁用 SELinux)
  • 嗨,Ivan,是的,文件夹上的chmod 777 返回相同的结果。
猜你喜欢
  • 2017-08-06
  • 1970-01-01
  • 2021-10-03
  • 2018-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-13
  • 2011-10-20
相关资源
最近更新 更多