Proof-of-concept solution for presenting XML services as a JSON API. This showcases:
js_header_filter
and js_body_filter
directives (requires njs 0.5.2 or later)This PoC uses the xml-js
Node.js module as a library to perform transformation between XML and JSON formats. The NGINX JavaScript module can use npm modules, provided that njs supports the ECMAScript objects and primitives that were used.
In this case we can use xml-js
as-is, and keep that code in a separate file for ease of maintenance. The Dockerfile includes the necessary steps to produce the module in a way that can be consumed by other njs functions. To do this manually, follow these steps:
xml-js
moduleglobal
namespace. Instead of using require('xml-js')
we can now use global.xmljs
$ echo "global.xmljs = require('xml-js');" | npx browserify -d -o xml-js.js -
$ cat << EOF >> xml-js.js export default {xj} function xj(){} EOF
Learn more about using Node.js modules with njs.
Transforming XML responses (GET-only)For XML services that offer a read-only (GET
) interface, i.e. clients don't send request bodies, we can use js_body_filter
to examine and modify the responses. The function is called for every buffer (part of the response) and so to perform full transformation of the response we must wait until we receive the last byte, indicated with flags.last
. At this point we can use r.sendBuffer()
to send whatever we like to the client.
js_body_filter
can be used inside a proxy_pass
location and so requires minimal config changes.
As the size of the response is likely to change, and the response format is different it is also important to modify the response headers, not just the body. We can use the js_header_filter
directive to call a separate function for this. The Content-Length
response header is removed so we rely on chunked encoding instead. The Content-Type
response header is replaced with application/json
to match the new body.
See the /api/f1
configuration for an example
For URIs that may also receive a request body that requires transformation (as well as the response) we cannot rely on js_body_filter
as that only handles responses. Bi-directional transformations can be achieved by splitting the location
block into three parts:
location
that handles configuration for the client-to-nginx processing (all of the pre-content phases) and delegates content to js_content
that executes;location
that handles configuration for the nginx-to-backend processingSee the /echo
configuration for an example
Build
Clone this repo, then
$ docker build -t nginx:xmljs .
Run
$ docker run -d -p 8000:80 -v $PWD:/etc/nginx/conf.d nginx:xmljs
Test
$ curl localhost:8000/api/f1/circuits/silverstone $ curl localhost:8000/echo $ curl localhost:8000/echo -d '{"foo":"bar"}'
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4