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.
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:
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:
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.
The Echo API backend:
-
Has the private endpoint:
https://echo-api.3scale.net
- Contains 2 mapping rules with the following patterns:
-
Has the private endpoint:
/hello /bye
The Cool API product:
-
Has this public endpoint:
https://cool.api
-
Uses the Echo API backend with this routing path:
/echo
.
-
Has this public endpoint:
- Mapping rules with the following patterns are automatically part of the Cool API product:
/echo/hello /echo/bye
-
This means that a request sent to the public URL
https://cool.api/echo/hello
is redirected tohttps://echo-api.3scale.net/hello
-
Similarly, a request sent to
https://cool.api/echo/bye
redirects tohttps://echo-api.3scale.net/bye
Now, consider an additional product called Tools For Devs using the same Echo API backend.
The Tools For Devs product:
-
Has public endpoint:
https://dev-tools.api
-
Uses the Echo API backend with the following routing path:
/tellmeback
.
-
Has public endpoint:
Mapping rules with the following patterns are automatically part of the Tools For Devs product:
/tellmeback/hello /tellmeback/bye
-
Therefore, a request sent to the public URL
https://dev-tools.api/tellmeback/hello
is redirected tohttps://echo-api.3scale.net/hello
-
Similarly, a request sent to
https://dev-tools.api/tellmeback/bye
redirects tohttps://echo-api.3scale.net/bye
-
Therefore, a request sent to the public URL
If you add a mapping rule with the
/ping
pattern to the Echo API backend, both products - Cool API and Tools For Devs- are affected:-
Cool API will have a mapping rule with this pattern:
/echo/ping
-
Tools For Devs will have a mapping rule with this pattern:
/tellmeback/ping
-
Cool API will have a mapping rule with this pattern:
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
, orPUT
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:
- Click Add Mapping Rule.
Specify the following settings:
-
Verb: The HTTP request verb (
GET
,POST
,DELETE
, orPUT
). -
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.
-
Verb: The HTTP request verb (
- 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.
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.
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.
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 -
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
, includingTraceContextHeaderName
which we will use to track requests
-
set a
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
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
Find the URL the Jaeger interface is running on:
oc get route (…) jaeger-query-myproject.127.0.0.1.nip.io
- Open the Jaeger interface from the previous step, which shows data being populated from Openshift Health checks.
- 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: