1

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;
         }
    }
}
Alessandro
  • 161
  • 1
  • 1
  • 15
  • I think this can be done with [openresty](https://github.com/openresty/openresty) or [ngx_http_lua_module](https://github.com/openresty/lua-nginx-module). Also see [this](https://stackoverflow.com/questions/22788236/how-can-i-manipulate-the-json-body-of-a-post-request-using-nginx-and-lua) question. – Ivan Shatsky Dec 04 '18 at 08:51
  • Hello Ivan, thanks for your response. Should this work also with the request headers? Thanks – Alessandro Dec 04 '18 at 09:32
  • As far as I know, for manipulations with request headers there is [ngx.req.get_headers](https://github.com/openresty/lua-nginx-module#ngxreqget_headers) and [ngx.req.set_header](https://github.com/openresty/lua-nginx-module#ngxreqset_header) methods. – Ivan Shatsky Dec 04 '18 at 09:40
  • Hello Ivan, I have tried to configure those modules, and they seem to be correctly installed. However, I can't seem to be able to perform a simple replacement of the string. Plus, the header directive doesn't overwrite anything unfortunately. I'll update the question with the configuration. – Alessandro Dec 05 '18 at 12:46

1 Answers1

0

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.

Ivan Shatsky
  • 13,267
  • 2
  • 21
  • 37
  • Hi Ivan, thanks a lot for your script, it certainly points me in the right direction. When I try to run the SOAP query, the error log contains the following: "client_body_temp/00000000005 failed (13:permission denied)". Did this error ever occur to you in the past? I tried some Google-Fu, but to no avail as of yet. I guess it's a problem with permissions to such folder, but with chmod/chown, i can't seem to be able to figure out. Thanks again for any insights – Alessandro Dec 06 '18 at 11:43
  • No, this error never occurs to me, but it is definitely somehow permissons-related. What is the full path to `client_body_temp` directory in your error log? Does this directory exists? What permissions does it have, what are its `owner` and `group` attributes? Under which user openresty worker processes are running? (`ps aux|grep nginx`) Do you have SELinux enabled? – Ivan Shatsky Dec 06 '18 at 12:59
  • Hi Ivan, the full error is below: `2018/12/06 15:04:04 [crit] 1607#1607: *4 open() "/root/work/client_body_temp/0000000004" failed (13: Permission denied)`. The directory exists and was created upon testing the script. I tried changing the permissions to user: nginx.nginx, nobody.nobody, but the result appears to be the same error. The master processes run as root, but the worker processes run as "nobody" user. SELinux was enabled, but disabling it with `setenforce 0` doesn't change the situation. – Alessandro Dec 06 '18 at 13:09
  • `chmod 777 client_body_temp` does not change the situation? (Keep SELinux disabled while we do not find a source of problem) – Ivan Shatsky Dec 06 '18 at 13:21
  • Hi Ivan, Yes `chmod 777` on the folder returns the same result. – Alessandro Dec 06 '18 at 13:33
  • Hm, it seems I'm out if ideas right now. What distro do you use? I can try to reproduce this error under virtualbox, but not before the weekend. Or you can try to open a new question, maybe somebody knows the answer. – Ivan Shatsky Dec 06 '18 at 13:47
  • I used CentOS 7 as a distribution, with Nginx openresty/1.13.6.2. I can't ask you to see it over the weekend, I've asked too much of you already! :) In fact, if you're ever in Milano, Italy I'll owe you at least a pizza :) In the meantime, I'll grant you the answer. Thanks again – Alessandro Dec 06 '18 at 13:54