Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Free tier API with Apache APISIX
Apache APISIX profile imageNicolas Fränkel
Nicolas Fränkel forApache APISIX

Posted on • Originally published atblog.frankel.ch

     

Free tier API with Apache APISIX

Lots of service providers offer a free tier of their service. The idea is to let you kick their service's tires freely. If you need to go above the free tier at any point, you'll likely stay on the service and pay. In this day and age, most services are online and accessible via an API. Today, we will implement a free tier withApache APISIX.

A naive approach

I implemented a free tier in my postEvolving your RESTful APIs, a step-by-step approach, albeit in a very naive way. I copy-pasted thelimit-count plugin and added my required logic.

function_M.access(conf,ctx)core.log.info("ver: ",ctx.conf_version)-- no limit if the request is authenticatedlocalkey=core.request.header(ctx,conf.header)#1ifkeythenlocalconsumer_conf=consumer_mod.plugin("key-auth")#2ifconsumer_confthenlocalconsumers=lrucache("consumers_key",consumer_conf.conf_version,#3create_consume_cache,consumer_conf)localconsumer=consumers[key]#4ifconsumerthen#5returnendendend-- rest of the logic
Enter fullscreen modeExit fullscreen mode
  1. Get the configured request header value
  2. Get the consumer'skey-auth configuration
  3. Get consumers
  4. Get the consumer with the passed API key if they exist
  5. If they exist, bypass the rate limiting logic

The downside of this approach is that the code is now my own. It has evolved since I copied it, and I'm stuck with the version I copied. We can do better, with the help of thevars parameter on routes.

APISIX route matching

APISIX delegates its matching rule to arouter.
Standard matching parameters include:

  • The URI
  • The HTTP method. By default, all methods match.
  • The host
  • The remote address

Most users do match on the URI; a small minority use HTTP methods and the host. However, they are not the only matching parameters. Knowing the rest will bring you into the world of advanced users of APISIX.

Let's take a simple example, header-based API versioning. You'd need actually to match a specific HTTP request header. I've already described how to do itpreviously. In essence,vars is an additional matching criterion that allows the evaluation of APISIX and nginx variables.

routes:-uri:/*upstream_id:1vars:[["http_accept","==","vnd.ch.frankel.myservice.v1+json"]]
Enter fullscreen modeExit fullscreen mode

The above route will match if, and only if, the HTTPAccept header is equal tovnd.ch.frankel.myservice.v1+json. You can find the complete list of supported operators in thelua-resty-expr project.

APISIX matches routes in a non-specified order by default. If URIs aredisjointed, that's not an issue.

routes:-uri:/*upstream_id:1vars:[["http_accept","==","vnd.ch.frankel.myservice.v1+json"]]-uri:/*upstream_id:2vars:[["http_accept","==","vnd.ch.frankel.myservice.v2+json"]]
Enter fullscreen modeExit fullscreen mode

Problems arise when URIs are somehow not disjointed. For example, imagine I want to set a default route for unversioned calls.

routes:-uri:/*upstream_id:1vars:[["http_accept","==","vnd.ch.frankel.myservice.v1+json"]]-uri:/*upstream_id:2vars:[["http_accept","==","vnd.ch.frankel.myservice.v2+json"]]-uri:/*upstream_id:1
Enter fullscreen modeExit fullscreen mode

We need the third route to be evaluated last. If it's evaluated first, it will match all requests, regardless of their HTTP headers. APISIX offers thepriority parameter to order route evaluation. By default, a route's priority is 0. Let's usepriority to implement the versioning correctly:

routes:-uri:/*upstream_id:1vars:[["http_accept","==","vnd.ch.frankel.myservice.v1+json"]]priority:10#1-uri:/*upstream_id:2vars:[["http_accept","==","vnd.ch.frankel.myservice.v2+json"]]priority:10#1-uri:/*upstream_id:1
Enter fullscreen modeExit fullscreen mode
  1. Evaluated first. The order is not relevant since the URIs are disjointed.

Implementing free tier with matching rules

We are now ready to implement our free tier with matching rules.

The first route to be evaluated should be the one with authentication and no rate limit:

routes:-uri:/getupstream_id:1vars:[["http_apikey","~~",".*"]]#1plugins:key-auth:~#2priority:10#3
Enter fullscreen modeExit fullscreen mode
  1. Match if the request has an HTTP header namedapikey
  2. Authenticate the request
  3. Evaluate first

The other route is evaluated afterward.

-uri:/getupstream_id:1plugins:limit-count:#1count:1time_window:60rejected_code:429
Enter fullscreen modeExit fullscreen mode
  1. Rate limit this route

When you configure APISIX with the above snippets, and it receives a request to/get, it tries to match the first routeonly if it has anapikey request header:

  1. If it has one:
    • Thekey-auth plugin kicks in
    • If it succeeds, APISIX forwars the request to the upstream
    • If it fails, APISIX returns a 403 HTTP status code
  2. If it has no such request header, it matches the second route with a rate limit.

Conclusion

A free tier is a must for any API service provider worth its salt. In this post, I've explained how to configure such free tier with Apache APISIX.

The complete source code for this post can be found on GitHub:

To go further:


Originally published atA Java Geek on July 28th, 2024

Top comments(1)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
sawyerwolfe profile image
Sawyer Wolfe
I appreciate your visit to my profile 👋
  • Joined

This is a great guide! Could you explain a bit more about how APISIX prioritizes routes when priorities are the same?

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

More fromApache APISIX

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp