Chapter 1. Operating APIcast

This section describes the concepts to consider when working with advanced APIcast configurations.

1.1. Public Base URL

The Public Base URL is the URL that your developers use to make requests to your API product, which is exposed publicly with 3scale. This will be the URL of your APIcast instance.

If you are using one of the Self-managed deployment options, you can choose your own Public Base URL for each one of the environments provided (staging and production) on a domain name you are managing. This URL should be different from the one of your API backend, and could be something like https://api.yourdomain.com:443, where yourdomain.com is the domain that belongs to you. After setting the Public Base URL make sure you save the changes and, if necessary, promote the changes in staging to production.

Note

The Public Base URL that you specify must use a port that is available in your OpenShift cluster. By default, the OpenShift router listens for connections only on the standard HTTP and HTTPS ports (80 and 443). If you want users to connect to your API over some other port, work with your OpenShift administrator to enable the port.

APIcast will only accept calls to the hostname specified in the Public Base URL. As an example for Echo API, if you specify https://echo-api.3scale.net:443 as the Public Base URL, the correct call would be:

curl "https://echo-api.3scale.net:443/hello?user_key=YOUR_USER_KEY"

In case you do not have a public domain for your API, you can use the APIcast IP address in the requests, but you still need to specify a value in the Public Base URL field even if the domain is not real. In this case, make sure you provide the host in the Host header. For example:

curl "http://192.0.2.12:80/hello?user_key=YOUR_USER_KEY" -H "Host: echo-api.3scale.net"

If you are deploying on local machine, you can also just use "localhost" as the domain, so the Public Base URL will look like http://localhost:80, and then you can make requests like this:

curl "http://localhost:80/hello?user_key=YOUR_USER_KEY"

In case you have multiple API products, set this Public Base URL appropriately for each product. APIcast will route the requests based on the hostname.

1.2. Mapping rules

Based on the requests to your API, mapping rules define the metrics or methods that you want to report. The following is an example mapping rule:

Mapping Rules

This rule means that any GET requests that start with / will increment the metric hits by 1. This rule will match any request to your API. But most likely, you will change this rule because it is too generic, and often leads to double counts when more specific rules are added.

The following rules for the Echo API show more specific examples:

Hello World Mapping Rules

1.2.1. Mapping rules in products and backends

Mapping rules work at the API product and API backend levels. In this section, you will learn about the behavior of mapping rules at each level, as well as see an example to describe how mapping rules operate.

Mapping rules at the product level

  • The mapping rule takes precedence. This means that the product mapping rule is the first one to be evaluated.
  • The mapping rule is always evaluated, independent of which backend receives the redirected traffic.

Mapping rules at the backend level

  • When you add mapping rules to a backend, these are added to all the products bundling said backend.
  • The mapping rule is evaluated after the mapping rules defined at the product level.
  • The mapping rule is evaluated only if the traffic is redirected to the same backend the mapping rule belongs to.
  • The path of the backend for a product is automatically prepended to each mapping rule of the backend bundled to said product.

Example of mapping rules with products and backends

For this example, we start with a backend and a product.

/hello
/bye
  • The Cool API product:

    • Has this public endpoint: https://cool.api
    • Uses the Echo API backend with this routing path: /echo.
  • Mapping rules with the following patterns are automatically part of the Cool API product:
/echo/hello
/echo/bye

Now, consider an additional product called Tools For Devs using the same Echo API backend.

1.2.2. Matching of mapping rules

The matching of mapping rules is performed by prefix and can be arbitrarily complex. The notation follows OpenAPI and ActiveDocs specifications:

  • A mapping rule must start with a forward slash (/).
  • You can perform a match on the path over a literal string (for example, /hello).
  • Mapping rules can include parameters on the query string or in the body (for example, /{word}?value={value}). APIcast fetches the parameters in the following ways:

    • GET method: From the query string.
    • POST, DELETE, or PUT method: From the body.
  • Mapping rules can contain named wildcards (for example, /{word}). This rule will match anything in the placeholder {word}, making requests like /morning match the rule. Wildcards can appear between slashes or between slash and dot. Parameters can also include wildcards.
  • By default, all mapping rules are evaluated from first to last, according to the sort you specified. If you add a rule /v1, it will be matched for requests whose paths start with /v1 (for example, /v1/word or /v1/sentence).
  • You can add a dollar sign ($) to the end of a pattern to specify exact matching. For example, /v1/word$ will only match /v1/word requests, and will not match /v1/word/hello requests. For exact matching, you must also ensure that the default mapping rule that matches everything (/) has been disabled.
  • More than one mapping rule can match the request path, but if none matches, the request is discarded with an HTTP 404 status code.

1.2.3. Mapping rules workflow

Mapping rules have the following workflow:

  • You can define a new mapping rule (see Add mapping rules).
  • Mapping rules will be grayed out on the next reload to prevent accidental modifications.
  • To edit an existing mapping rule, you must enable it first by clicking the pencil icon on the right.
  • To delete a rule, click the trash icon.
  • All modifications and deletions are saved when you promote the changes in Integration > Configuration.

Add mapping rules

To add a new mapping rule, perform the following steps:

  1. Click Add Mapping Rule.
  2. Specify the following settings:

    • Verb: The HTTP request verb (GET, POST, DELETE, or PUT).
    • Pattern: The pattern to match (for example, /hello).
    • Metric or method to increment: The metric or method name.
    • Increment by: The metric increment number (for example, 1).
    • Last?: If this mapping rule should be considered as the last one, to stop processing other mapping rules.
    • Position: Number that indicates the position of the execution of the mapping rule, to sort the mapping rules.
  3. Click Create Mapping Rule to apply the changes.

Stop other mapping rules

To stop processing other mapping rules, you can select Last? when creating a new mapping rule. For example, if you have the following mapping rules defined in API Integration Settings and you have different metrics associated with each rule:

(get) /path/to/example/search
(get) /path/to/example/{id}

When calling with (get) /path/to/example/search, APIcast stops processing the remaining mapping rules and incrementing their metrics after the rule is matched.

1.3. Host header

This option is only needed for those API products that reject traffic unless the Host header matches the expected one. In these cases, having a gateway in front of your API product will cause problems since the Host will be the one of the gateway, e.g. xxx-yyy.staging.apicast.io

To avoid this issue you can define the host your API product expects in the Host Header field in the Authentication Settings, and the hosted APIcast instance will rewrite the host.

Host Rewrite

1.4. Protecting your API backend

Once you have APIcast working in production, you might want to restrict direct access to your API product without credentials. The easiest way to do this is by using the Secret Token set by APIcast. Please refer to the Advanced APIcast configuration for information on how to set it up.

1.5. Using APIcast with private APIs

With APIcast it is possible to protect the APIs which are not publicly accessible on the Internet. The requirements that must be met are:

  • Self-managed APIcast must be used as the deployment option.
  • APIcast needs to be accessible from the public internet and be able to make outbound calls to the 3scale Service Management API.
  • The API product should be accessible by APIcast.

In this case you can set your internal domain name or the IP address of your API in the Private Base URL field and follow the rest of the steps as usual. Note, however, that you will not be able to take advantage of the Staging environment, and the test calls will not be successful, as the Staging APIcast instance is hosted by 3scale and will not have access to your private API backend). But once you deploy APIcast in your production environment, if the configuration is correct, APIcast will work as expected.

1.6. Configuring APIcast with OpenTracing

OpenTracing is an API specification and method used to profile and monitor microservices. From version 3.3 onwards, APIcast includes OpenTracing Libraries and the Jaeger Tracer library.

1.6.1. Prerequisites

To add distributed tracing to your APIcast deployment, you need to ensure the following prerequisites:

  • Each external request should have a unique request ID attached, usually via a HTTP header.
  • Each service should forward the request ID to other services.
  • Each service should output the request ID in the logs.
  • Each service should record additional information, like start and end time of the request.
  • Logs need to be aggregated, and provide a way to parse via HTTP request ID.

1.6.2. Procedure

To configure OpenTracing, use the following environment variables:

  • OPENTRACING_TRACER: To define which tracer implementation to use. Currently, only Jaeger is available.
  • OPENTRACING_CONFIG: To specify the default configuration file of your tracer. You can see an example here.
  • OPENTRACING_HEADER_FORWARD: Optional. You can set this environment variable according to your OpenTracing configuration.

For more information about these variables, refer to APIcast environment variables.

To test if the integration is properly working, you need to check if traces are reported in the Jaeger tracing interface.

1.6.3. Additional information

The OpenTracing and Jaeger integration are available in the upstream project: https://github.com/3scale/apicast

1.6.4. Installing Jaeger on your OpenShift instance

This section provides information about the installation of Jaeger on the OpenShift instance you are running.

Warning

Jaeger is a third-party component, which 3scale does not provide support for, with the exception of uses with APIcast. The following instructions are provided as a reference example only, and are not suitable for production use.

  1. Install the Jaeger all-in-one in the current namespace:

    oc process -f https://raw.githubusercontent.com/jaegertracing/jaeger-openshift/master/all-in-one/jaeger-all-in-one-template.yml | oc create -f -
  2. Create a Jaeger configuration file jaeger_config.json and add the following:

    {
        "service_name": "apicast",
        "disabled": false,
        "sampler": {
          "type": "const",
          "param": 1
        },
        "reporter": {
          "queueSize": 100,
          "bufferFlushInterval": 10,
          "logSpans": false,
          "localAgentHostPort": "jaeger-agent:6831"
        },
        "headers": {
          "jaegerDebugHeader": "debug-id",
          "jaegerBaggageHeader": "baggage",
          "TraceContextHeaderName": "uber-trace-id",
          "traceBaggageHeaderPrefix": "testctx-"
        },
        "baggage_restrictions": {
            "denyBaggageOnInitializationFailure": false,
            "hostPort": "127.0.0.1:5778",
            "refreshInterval": 60
        }
     }
    • set a sampler constant of 1 to sample all requests
    • set the location and queue size of the reporter
    • set headers, including TraceContextHeaderName which we will use to track requests
  3. Create a ConfigMap from our Jaeger configuration file and mount it into APIcast:

    oc create configmap jaeger-config --from-file=jaeger_config.json
    oc volume dc/apicast --add -m /tmp/jaeger/ --configmap-name jaeger-config
  4. Enable OpenTracing and Jaeger with the configuration we have just added:

    oc set env deploymentConfig/apicast OPENTRACING_TRACER=jaeger OPENTRACING_CONFIG=/tmp/jaeger/jaeger_config.json
  5. Find the URL the Jaeger interface is running on:

    oc get route
    (…) jaeger-query-myproject.127.0.0.1.nip.io
  6. Open the Jaeger interface from the previous step, which shows data being populated from Openshift Health checks.
  7. The final step is to add OpenTracing and Jaeger support to your backend APIs so that you can see the complete request trace. This varies in each back end, depending on the frameworks and languages used. As a reference example, you can see Using OpenTracing with Jaeger to collect Application Metrics in Kubernetes.

For more information on configuring Jaeger, see: