Nginx – Replacing JSON body before caching on nginx

dockernginx

I've been trying hardly to modify a JSON response from a web server before caching and returning it to the client, with no results.

I'm using docker, openresty alpine image and nginx.

My configuration starts with the docker file set this way:

FROM openresty/openresty:alpine

COPY ./nginx.conf /etc/nginx/conf.d/default.conf

EXPOSE 80

CMD ["/usr/local/openresty/bin/openresty", "-g", "daemon off;"]

Then my nginx.conf file looks this way:

proxy_cache_path /var/cache levels=1:2 keys_zone=default_zone:10m max_size=10g inactive=10d use_temp_path=off;

server {
  listen 80;

  location / {
    # Proxy settings
    proxy_pass              http://www.some-site.com;
    proxy_cache             default_zone;
    proxy_cache_methods     GET;
    proxy_cache_valid       100d;

    proxy_ignore_headers    Cache-Control;
  }
}

I've been trying to get the response from the server by having a lua block, with no success, and also by using cjson lib in order to parse it.
The questions I've got so far are these ones:

How can I get the response body of http://www.some-site.com?

Also, assuming that the JSON file looks like this:

{
  "fields": [{
    "someUrl": "http://www.some-other-site.com/resource/some-resource"
  }]
}

How can I modify every key called someUrl by having this on an object that is inside an array, and can contain multiple objects with the same key?

For instance, what I'm trying to do is to replace the domain for the same domain that is running my server. I have it configured to point to port 4080, so I want this object to be something like this before both, sending the response to the client and caching, so the response body looks something like this:

{
  "fields": [{
    "someUrl": "http://localhost:4080/resource/some-resource"
  }]
}

I know that I would have to use a regex in order to replace the domain, but for the other issues I'm mentioning, I'm really lost. Been trying to look at google, searching specifics, by reading nginx documentation, and still really lost.

Thanks a lot folks!!

Best Answer

Already solve the issue.

Lucky me, openresty has built-in support for ngx_http_sub_module.

This is what I had to do in order to get it work:

proxy_cache_path /var/cache levels=1:2 keys_zone=default_zone:10m max_size=10g inactive=10d use_temp_path=off;

server {
  listen 80;

  location / {

    # Have to escape slashes:
    sub_filter "http:\/\/www.some-site.com" "$scheme://$host";

    # Disable sub_filter_once as I can have multiple keys to affect
    sub_filter_once off;

    # Sub filter type to accept application/json (mandatory)
    sub_filter_types        application/json;

    # Disable compressed response, as Content-Encoding the site is gzip
    proxy_set_header        Accept-Encoding "";

    # Proxy settings
    proxy_pass              http://www.some-site.com;
    proxy_cache             default_zone;
    proxy_cache_methods     GET;
    proxy_cache_valid       100d;

    proxy_ignore_headers    Cache-Control;
  }
}