Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rate Limit policy: allow templating using liquid #719

Merged
merged 1 commit into from
Jun 1, 2018

Conversation

y-tabata
Copy link
Contributor

@y-tabata y-tabata commented May 22, 2018

Closes #713.

@@ -984,3 +990,106 @@ Return 200 code.
["GET /","GET /"]
--- error_code eval
[200, 200]

=== TEST 17: Liquid templating (jwt.aud).
Return 429 code.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be more descriptive.

@davidor
Copy link
Contributor

davidor commented May 22, 2018

@y-tabata Thanks for your contribution! 👍

Can you add a changelog entry, please? Something like Liquid templating support in the rate-limit policy under the Added section would be enough.

Also, could you add some unit tests for this? I see that you added some integration tests which is good 👍 , but we also need the unit ones. You can use the ones we added for the headers policy as an example: #716


$ENV{TEST_NGINX_LUA_PATH} = "$Test::APIcast::spec/?.lua;$ENV{TEST_NGINX_LUA_PATH}";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to resolve 'fixtures.rsa'.
I referenced apicast-oidc.t.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. I think we can find a better solution. I think these tests should make use of the fixtures directory in t instead of the one in spec. However, as you said, we're doing the same in apicast-oidc.t. We should fix this, but I think we can do it after this PR.

@y-tabata y-tabata force-pushed the liquid-templating-rate-limit-policy branch from 62e781d to 7cbc4aa Compare May 23, 2018 00:46
end
limiter.key_name = key_name
else
limiter.key_name = limiter.template_string:render(context)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your solution works, but I think there's a simpler way to solve the same problem.

What we want to do is to make ngx.var.uri and ngx.var.host available in the liquid templates.

The regex matching is not necessary. We can achieve our goal by including new keys in the context we pass to template_string:render(context). If that context includes a table with these keys uri = ngx.var.uri and host = ngx.var.host we'll be able to use {{ uri }} and {{ host }} in the config instead of {{ ngx.var.uri }} and {{ ngx.var.host }}.

Another option is to include ngx.var.host in the context that we send to template_string:render(). However, I think that when configuring this from the 3scale UI, users will find it more natural to write {{host}} than to write {{ngx.var.host}}. In theory, they don't even need to know that apicast is based on nginx. I had a discussion with @mikz about this in another PR: #716 (comment)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we don't use the regex, we have to have the list like uri = ngx.var.uri or host = ngx.var.host and so on.
The best place is liquid_filters of template_string.lua, isn't it?
Do you have any idea to avoid the "API disabled in the current context" error?

Copy link
Contributor

@davidor davidor May 28, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think liquid_filters in template_string.lua is the best place for this. Those are filters, functions like md5 that allow us to have things like {{ 'a_value' | md5 }} in the policy config.

But uri and host are values, not filters. I think uri and host need to be included in the context passed to render. For that, I think a possible solution is to have a table somewhere with the values we want to have available in the context. As a starting point, we could have something like:

local function context_values()
  return {
    uri = ngx.var.uri,
    host = ngx.var.host,
    -- possibly many others
  }
end

_M.available_context(policies_context)
  -- merge policies_context with context_values and return the result
end

Maybe we could include this in the Policy module or even in a new separate module.

If we evaluate the ngx.var* vars in access(), we won't see the API disabled in the current context error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed.

@y-tabata y-tabata force-pushed the liquid-templating-rate-limit-policy branch from f63f876 to bdc32d8 Compare May 29, 2018 00:48
end

function _M.available_context(policies_context)
for name, value in pairs(context_values()) do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pairs method can't be JITed, it is always better to use ipairs and change the data structure.

In this case it is not even needed. What are you doing is mutating the passed policies_context. That is really not expected. It is way better to return a new object.

You don't need to even copy the context table, just use metatable __index property to delegate unknown fields:

return setmetatable(context_values(), { __index = policies_context })


local function interpolate_key_name(context, limiters)
for _, limiter in ipairs(limiters) do
limiter.key_name = limiter.template_string:render(context)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This mutates the limiter object which is shared across all requests.

You can just pass context to build_limiters_and_keys and use it there without storing it in the shared limiter object.

@y-tabata y-tabata force-pushed the liquid-templating-rate-limit-policy branch 3 times, most recently from c0b91f8 to c1ddc21 Compare June 1, 2018 04:54
@y-tabata
Copy link
Contributor Author

y-tabata commented Jun 1, 2018

Do you have any idea to avoid prove errors?
These tests succeeded in my local environment, and I remember 3 days ago the tests succeeded here, too.

end

function _M.available_context(policies_context)
return setmetatable(policies_context, { __index = context_values() })
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still mutates the context. It should be the other way around. Setting the metatable of context_values.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@mikz
Copy link
Contributor

mikz commented Jun 1, 2018

@y-tabata the tests fail because of #719 (comment)

@y-tabata y-tabata force-pushed the liquid-templating-rate-limit-policy branch from c1ddc21 to a31bc40 Compare June 1, 2018 08:21
@y-tabata
Copy link
Contributor Author

y-tabata commented Jun 1, 2018

@mikz thanks!

Copy link
Contributor

@mikz mikz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 good job!

@mikz mikz added this to the 3.3 milestone Jun 1, 2018
Copy link
Contributor

@davidor davidor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good 👍
Thanks for your contribution @y-tabata ! 👍

@davidor davidor merged commit 6a48e85 into 3scale:master Jun 1, 2018
@y-tabata y-tabata deleted the liquid-templating-rate-limit-policy branch June 1, 2018 14:03
@mikz mikz mentioned this pull request Jun 12, 2018
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants