Relative Links with IBM Cloud API Gateway

I work quite a bit with serverless tech, particularly on IBM Cloud since I work there. At the moment I'm building a microservice using web actions. When a user creates data with a POST request, I want to redirect them to the URL of the new thing they created - but for that I need to know the URL that it was accessed with. This is a relatively new feature on API Gateway so here's a quick howto for grabbing that URL in both JavaScript and PHP.

Get the requested URL with JavaScript

Here's a very simple prototype JavaScript action showing how to grab the URL that this action was requested with, and both log and return it:

function main(params) {
    var base_url = params['__ow_headers']['x-forwarded-url'];
    console.log("Base URL: " + base_url);
    return {body: "New item at " + base_url + "/42"};
}

exports.main = main;

This shows how to find the base_url that this request came in on. My code is deployed to a url-demo package with this command:

bx wsk action update --kind nodejs:8 --web raw url-demo/js index.js

This creates the action, indicates which runtime to use (nodejs:8) and also sets the action up with --web raw which means that we can access the headers, body, method, query and path of the incoming request, without any additional parsing. There are also helper options that, for example, will parse incoming JSON but I prefer to see and parse the request as it arrived and know where all my data came from!

To set up the web routing, we use the API Gateway:

bx wsk api create /demo-js GET url-demo/js --response-type http

This command returns a URL that we can then call, either with cURL or simply by pasting it into your browser. The response will show the same URL with /42 appended (which you probably guessed from the code above!).

Get the requested URL with PHP

Since I'm writing a microservice in a bunch of different programming languages, here's the same example again for PHP. First the code for the function:

<?php

function main(array $params) : array
{
    $base_url = params['__ow_headers']['x-forwarded-url'];
    var_dump("Base URL: " . $base_url);
    return ["body" => "New item at " . $base_url . "/42"];
}

Next the commands to deploy the serverless action and set an API Gateway endpoint to talk to it:

bx wsk action update --kind php:7.1 --web raw url-demo/php index.php
bx wsk api create /demo-php GET url-demo/php --response-type http

Exactly as before, this pushes our code to the cloud as a serverless action, and then sets up an API route to point to it. The second command returns a URL, you can request it and see output that uses the requested URL as part of it.

This feature makes it easier to offer sensible pagination, relative links and other API goodness from the IBM Cloud Functions and API Gateway projects I work on. I like it a lot and hopefully these examples will be useful to anyone looking to build a similar project themselves.

3 thoughts on “Relative Links with IBM Cloud API Gateway

  1. Note that once you have added an additional segment to the `x-forwarded-for` value, then the next request will have that segment in its own `x-forwarded-for` value. i.e. `x-forwarded-for` contains the full URL that was requested by the client

    For example. Let's say that you start with an `x-forwarded-for` of `https://example.com/foo/bar/url-demo/php` and you respond with the new item's URL of `https://example.com/foo/bar/url-demo/php/42`. When the client requests the new URL, the `x-forwarded-for` will contain the `https://example.com/foo/bar/url-demo/php/42` which is not the original `base_url`.

    You can look in `params['__ow_path']` to find this addition and so remove it from `x-forwarded-for` to get back to your original `base_url`.

  2. Pingback: Using Fractal as your OpenWhisk API’s view layer – Rob Allen's DevNotes

  3. Pingback: Using Fractal as your OpenWhisk API's view layer - webdev.am

Mentions