Case Study Jobteaser Case Study: Scalable Public APIs with KrakenD

You are viewing a previous version of KrakenD Enterprise Edition (v2.0), go to the latest version

Document updated on Aug 29, 2022

Modify requests and responses with Martian

The krakend-martian component allows you to transform requests and responses through a simple DSL definition in the configuration file. Martian works perfectly in combination with CEL verifications.

Use Martian when you want to intercept the end-user’s request and make modifications before passing the content to the backends. Also, the other way around, transform the backends response before passing it to the user.

Martian is mighty and gives you endless possibilities to control what is going in and out of the gateway. Some examples of typical Martian scenarios are:

  • Set a new cookie during gateway processing
  • Add, remove or change specific headers
  • Query string additions before making the backend request (e.g., set an API key)

There are four different types of interactions you can do with Martian:

  • Modifiers: Change the state of a request or a response. For instance, you want to add a custom header in the request before sending it to a backend.
  • Filters: Add a condition to execute a contained Modifier
  • Groups: Bundle multiple operations to execute in the order specified in the group
  • Verifiers: Track network traffic against expectations

Transforming requests and responses

Add martian modifiers in your configuration under the extra_config of any backend using the namespace modifier/martian.

Your configuration has to look as follows:

{
    "extra_config": {
        "modifier/martian": {
            // modifier configuration here
        }
    }
}

See the possibilities and examples below.

A note on client headers
When client headers are needed, remember to add them under input_headers as KrakenD does not forward headers to the backends unless declared in the list.

Modifier configuration

In the examples below, you’ll find that all modifiers have a configuration key named scope. The scope indicates when to apply the modifier. It can be an array containing request, response, or both. The rest of the keys in every modifier depends on the modifier itself.

Transform headers

The header.Modifier injects a header with a specific value. For instance, the following configuration adds a header X-Martian both in the request and the response.

{
    "extra_config": {
        "modifier/martian": {
            "header.Modifier": {
              "scope": ["request", "response"],
              "name": "X-Martian",
              "value": "true"
            }
        }
    }
}

Modify the body

Through the body.Modifier, you can modify the body of the request and the response. You must encode in base64 the content of the body.

The following modifier sets the body of the request and the response to {"msg":"you rock!"}. Notice that the body field is base64 encoded.

{
    "extra_config": {
        "modifier/martian":
          {
              "body.Modifier": {
                  "scope": ["request","response"],
                  "body": "eyJtc2ciOiJ5b3Ugcm9jayEifQ=="
              }
          }
    }
}

Transform the URL

The url.Modifier allows you to change settings in the URL. For instance:

{
    "extra_config": {
        "modifier/martian": {
            "url.Modifier": {
              "scope": ["request"],
              "scheme": "https",
              "host": "www.google.com",
              "path": "/proxy",
              "query": "testing=true"
            }
        }
    }
}

Copying headers

Although not widely used, the header.Copy lets you duplicate a header using another name.

{
    "extra_config": {
        "modifier/martian": {
            "header.Copy": {
                "scope": ["request", "response"],
                "from": "Original-Header",
                "to": "Copy-Header"
            }
        }
    }
}

Apply multiple modifiers consecutively

All the examples above perform a single modification in the request or the response. However, the fifo.Group allows you to create a list of modifiers that execute consecutively. The group is needed when using more than one modifier and encapsulates all the following actions to perform in the modifiers array. You can use the FIFO group even when there is only one modifier in the list.

Example of usage (modify the body, and set a header):

{
    "extra_config": {
        "modifier/martian": {
            "fifo.Group": {
                "scope": ["request", "response"],
                "aggregateErrors": true,
                "modifiers": [
                    {
                        "body.Modifier": {
                            "scope": ["request"],
                            "body": "eyJtc2ciOiJ5b3Ugcm9jayEifQ=="
                        }
                    },
                    {
                        "header.Modifier": {
                        "scope": ["request", "response"],
                        "name": "X-Martian",
                        "value": "true"
                      }
                    }
                ]
            }
        }
    }
}

Connecting to Basic Auth (user/pass) backends

Sometimes your backends are protected, and you need KrakenD to provide a user and password to connect. The basic authentication requires you to provide a header with the form Authorization: Basic <credentials>. The credentials are the concatenation of the username and password using a colon : in base64.

For instance, if your username is user and your password pa55w0rd, you should generate the base64 as follows:

Term 

$echo -n "user:pa55w0rd" | base64
dXNlcjpwYTU1dzByZA==

When using echo, make sure to add the -n option to avoid the final line break from being encoded. You can test if the connection succeeds now with:

Term 

$curl -i https://yourapi --header 'Authorization: Basic dXNlcjpwYTU1dzByZA=='

If the connection works, it means that your credentials are correct, and you can add the resulting base64 string dXNlcjpwYTU1dzByZA== to the Martian modifier right before connecting to your backend:

{
    "url_pattern": "/protected",
    "extra_config": {
        "modifier/martian": {
            "header.Modifier": {
              "scope": ["request"],
              "name": "Authorization",
              "value": "Basic dXNlcjpwYTU1dzByZA=="
            }
        }
    }
}

With the configuration above, whenever a request is made to the backend, the Authorization header is added automatically.

For more complex examples of authentication using Martian, see the example Adding automatic API authentication

All Martian modifiers, verifiers, and filters

The Martian library comes with +25 modifiers you can use. We are not listing all the options in the documentation. Instead, we provided the modifiers that are key when using Martian.

For the complete list of modifiers and usage, see Google’s Martian repository. These are the packages included in KrakenD-CE:

Building new modifiers

Sometimes you want to create a new modifier that covers your specific use case and does some other dynamic operations. Creating more modifiers is a straightforward process and only requires make the gateway once you have it coded.

Nothing better than an example to demonstrate how to create a new modifier. Our SRE Director (who wasn’t familiar with Go) went through the process of creating a new Modifier that would authenticate automatically against the Marvel API, adding an API Key, a timestamp, and a calculated hash.

Read it here (contains the source code): Martian example: Adding automatic API authentication

Scarf

Unresolved issues?

The documentation is only a piece of the help you can get! Whether you are looking for Open Source or Enterprise support, see more support channels that can help you.

See all support channels