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

feat(plugin): azure serverless functions #5479

Merged
merged 10 commits into from
Nov 19, 2021

Conversation

bisakhmondal
Copy link
Member

@bisakhmondal bisakhmondal commented Nov 10, 2021

What this PR does / why we need it:

Pre-submission checklist:

  • Did you explain what problem does this PR solve? Or what new features have been added?
  • Have you added corresponding test cases?
  • Have you modified the corresponding document?
  • Is this PR backward compatible? If it is not backward compatible, please discuss on the mailing list first

@bisakhmondal bisakhmondal changed the title feat: azure serverless functions plugin support feat(plugin): azure serverless functions Nov 10, 2021
@bisakhmondal bisakhmondal marked this pull request as ready for review November 16, 2021 14:36
function _M.access(conf, ctx)
local uri_args = core.request.get_uri_args(ctx)
local headers = core.request.headers(ctx) or {}
local req_body, _ = core.request.get_body()
Copy link
Contributor

Choose a reason for hiding this comment

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

What if the request body are large and we cannot load it into memory totally?

Copy link
Member

Choose a reason for hiding this comment

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

The body will be missing when it is larger than client_body_buffer_size (8k by default)
We can read the body by ourselves via ngx.req.socket? See https://github.com/openresty/lua-resty-upload/blob/master/lib/resty/upload.lua

We can do it in the next PR.

Copy link
Member

Choose a reason for hiding this comment

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

I just realize it uses core.request.get_body, which will read data from file if need. BTW, we should check the err returned by this function.

Copy link
Member Author

Choose a reason for hiding this comment

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

thanks for pointing it out @tokers!
@spacewander even if it reads the content from a file, it reads everything in one go

local function get_file(file_name)
local f, err = io_open(file_name, 'r')
if not f then
return nil, err
end
local req_body = f:read("*all")
f:close()
return req_body
end

I think we should use chunked transfer encoding here to proxy the request with a large body size. WDYT?

Copy link
Member

Choose a reason for hiding this comment

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

I think normally people don't need to submit big data to azure functions. We can keep this function unchanged for now.

Copy link
Contributor

Choose a reason for hiding this comment

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

Agree, but it's better to add some hints in the document. @bisakhmondal @spacewander

local res, err = httpc:request_uri(conf.function_uri, params)

if not res or err then
return core.response.exit(500, "failed to process azure function, err: " .. err)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
return core.response.exit(500, "failed to process azure function, err: " .. err)
core.log.error("failed to process azure function, err: " .. err)
return 503

I think it will be safer not to return an internal error to the client.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ack

@@ -340,6 +340,7 @@ plugins: # plugin list (sorted by priority)
- response-rewrite # priority: 899
#- dubbo-proxy # priority: 507
- grpc-transcode # priority: 506
- azure-functions # priority: 505
Copy link
Member

Choose a reason for hiding this comment

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

Better to put it ahead of serverless-post-function

Copy link
Member Author

Choose a reason for hiding this comment

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

What should be the priority value, negative?

Copy link
Member

Choose a reason for hiding this comment

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

priority: -1900?

add_block_preprocessor(sub {
my ($block) = @_;

if (!defined $block->additional_http_config) {
Copy link
Member

Choose a reason for hiding this comment

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

We can use http_config to inject HTTP config, see https://github.com/apache/apisix/blob/master/t/discovery/consul_kv.t

And I suggest you put azure-demo as

function _M.hello()

There is no need to introduce a new server.

Copy link
Member Author

Choose a reason for hiding this comment

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

Gotcha

Copy link
Member Author

Choose a reason for hiding this comment

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

Done, Is it okay now?

headers["x-functions-key"] = conf.authorization.apikey or ""
headers["x-functions-clientid"] = conf.authorization.clientid or ""
else
headers["x-functions-key"] = getenv(env_key.API)
Copy link
Member

Choose a reason for hiding this comment

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

We need to expose the AZURE_FUNCTIONS_APIKEY via env AZURE_FUNCTIONS_APIKEY, if this plugin is enabled. Nginx will hide all environment variables by default.

Copy link
Member Author

Choose a reason for hiding this comment

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

You mean like this env AZURE_FUNCTIONS_APIKEY="key" make run?
Or you are suggesting to update something?

Copy link
Member

Choose a reason for hiding this comment

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

Like

env PATH; # for searching external plugin runner's binary
, but only when this plugin is enabled:
{% if enabled_plugins["proxy-cache"] then %}

Copy link
Member

Choose a reason for hiding this comment

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

I change my mind. Maybe it could be easier to pass this argument via plugin metadata.

Copy link
Member Author

Choose a reason for hiding this comment

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

Metadata won't be a great fit, IMHO. There might be multiple instances of plugins linked to different routes and we can't force users to use the same key they put into the metadata schema(must be the master key, instead of function-specific keys). This clearly violates principle of Least Access Privileges, isn't it?

Copy link
Member Author

Choose a reason for hiding this comment

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

Removed env vars and added metadata as a fallback option

method = ngx.req.get_method(),
body = req_body,
query = uri_args,
headers = headers,
Copy link
Member

Choose a reason for hiding this comment

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

Do we need to remove the host header? Otherwise, the host of APISIX will be used.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done, It was the root of many problem.

=== TEST 5: http2 check response body and headers
--- http2
--- exec
curl -XGET --http2 --http2-prior-knowledge localhost:1984/azure
Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

Nice, it is. Updated

apisix/plugins/azure-functions.lua Outdated Show resolved Hide resolved
bisakhmondal and others added 2 commits November 18, 2021 10:38
Co-authored-by: 罗泽轩 <spacewanderlzx@gmail.com>
@bzp2010
Copy link
Contributor

bzp2010 commented Nov 18, 2021

I have a question, should we standardize the naming of all serverless plugins? such as xxx-function or xxx-serverless 🤔

@spacewander
Copy link
Member

@bzp2010
I think we can use the product name directly (azure-functions in this case). It is easier to be searched.

@membphis membphis merged commit 3a6a4db into apache:master Nov 19, 2021
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.

6 participants