Is it possible to rewrite SOAP POST request bodies

2019-08-10 07:58发布

问题:

I'm trying to rewrite a SOAP POST request body and header, so that Apache or Nginx can proxy it to an application which resides on another server.

The request is composed like this, this one in particular refers to the "UploadDocument_v4" functionality:

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>

What I need to do, is to rewrite this request so that it invokes the same function, but with the _v2 version. So, all the references to _v4 should be replaced with _v2 both within body AND header.

Is this possible in any way? I used Nginx and Apache up until now but with the relative modules I haven't yet been able to figure out a way to do this, if possible.

Thanks for any insights you might be able to provide.

UPDATE: As Ivan suggested in the comments, I tried to install Openresty, and by using a basic configuration, i'm able to ascertain that it is working. However, I can't seem to be able to figure out how to replace body and header. The nginx.conf file is below:

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;
         }
    }
}

回答1:

Ok, it is about two years passed since I wrote something in Lua, but I'll try :)

    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;
    }

I tested this config with curl and PHP script which print HTTP headers and POST request body, and it works. You can't use return 302 ... because your HTTP headers will be regenerated for a new request, you must use proxy_pass directive instead. Note that if you'll specify your proxy server by domain, not an IP address, you'll have to use proxy_set_header Host proxy-domain.com directive and possibly a resolver directive.