Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 8dbd8ea

Browse files
committed
adding oci-apigw-display-httprequest-info-python
1 parent c700d1e commit 8dbd8ea

File tree

9 files changed

+380
-0
lines changed

9 files changed

+380
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.DS_Store
2+
__pycache__
3+
test.py
Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
# Function that returns the HTTP request information when called through API Gateway
2+
This function returns the HTTP request information when called through API Gateway.
3+
4+
As you make your way through this tutorial, look out for this icon ![user input icon](./images/userinput.png).
5+
Whenever you see it, it's time for you to perform an action.
6+
7+
8+
## Prerequisites
9+
Before you deploy this sample function, make sure you have run step A, B and C of the [Oracle Functions Quick Start Guide for Cloud Shell](https://www.oracle.com/webfolder/technetwork/tutorials/infographics/oci_functions_cloudshell_quickview/functions_quickview_top/functions_quickview/index.html)
10+
* A - Set up your tenancy
11+
* B - Create application
12+
* C - Set up your Cloud Shell dev environment
13+
14+
15+
## List Applications
16+
Assuming your have successfully completed the prerequisites, you should see your
17+
application in the list of applications.
18+
```
19+
fn ls apps
20+
```
21+
22+
23+
## Review and customize the function
24+
Review the following files in the current folder:
25+
* the code of the function, [func.py](./func.py)
26+
* its dependencies, [requirements.txt](./requirements.txt)
27+
* the function metadata, [func.yaml](./func.yaml)
28+
29+
30+
## Deploy the function
31+
In Cloud Shell, run the *fn deploy* command to build the function and its dependencies as a Docker image,
32+
push the image to OCIR, and deploy the function to Oracle Functions in your application.
33+
34+
![user input icon](./images/userinput.png)
35+
```
36+
fn -v deploy --app <app-name>
37+
```
38+
39+
40+
## Create the API Gateway
41+
The functions is meant to be invoked through API Gateway.
42+
43+
![user input icon](./images/userinput.png)
44+
45+
On the OCI console, navigate to *Developer Services* > *API Gateway*. Click on *Create Gateway*. Provide a name, set the type to "Public", select a compartment, a VCN, a public subnet, and click *Create*.
46+
47+
![APIGW create](./images/apigw-create.png)
48+
49+
Once created, click on your gateway. Under *Resources*, select *Deployments* and click *Create Deployment*. Provide a name, a path prefix ("/v1" for example), click *Next*. Provide a name to the route ("/display-httprequest-info" for example), select methods "GET" and "POST", select type "Oracle Functions", select the Application for your function, and select your function you deployed in the previous step.
50+
51+
![APIGW deployment create](./images/apigw-deployment-create.png)
52+
53+
Click *Next* and finally, click *Save Changes*.
54+
55+
Note the endpoint of your API Gateway deployment.
56+
57+
![APIGW deployment endpoint](./images/apigw-deployment-endpoint.png)
58+
59+
60+
## Create or Update your Dynamic Group for API Gateway
61+
In order to invoke functions, your API Gateway must be part of a dynamic group.
62+
63+
When specifying the *Matching Rules*, we suggest matching all functions in a compartment with:
64+
```
65+
ALL {resource.type = 'ApiGateway', resource.compartment.id = 'ocid1.compartment.oc1..aaaaaxxxxx'}
66+
```
67+
68+
69+
## Create or Update IAM Policies for API Gateway
70+
Create a new policy that allows the API Gateway dynamic group to invoke functions. We will grant `use` access to `functions-family` in the compartment.
71+
72+
![user input icon](./images/userinput.png)
73+
74+
Your policy should look something like this:
75+
```
76+
Allow dynamic-group <dynamic-group-name> to use functions-family in compartment <compartment-name>
77+
```
78+
79+
For more information on how to create policies, check the [documentation](https://docs.cloud.oracle.com/iaas/Content/Identity/Concepts/policysyntax.htm).
80+
81+
82+
## Set the function configuration values
83+
The function returns the configuration values you set.
84+
85+
![user input icon](../images/userinput.png)
86+
87+
Use the *fn CLI* to set the config value:
88+
```
89+
fn config function <app-name> <function-name> <configkey> <configvalue>
90+
```
91+
e.g.
92+
```
93+
fn config function myapp oci-apigw-display-httprequest-info-python configkey1 "value1"
94+
```
95+
96+
97+
## Invoke the function
98+
The function returns the information of the HTTP request through API Gateway.
99+
100+
![user input icon](./images/userinput.png)
101+
102+
Set the Environment variable "APIGW_ENDPOINT" to the value of the endpoint of your API Gateway deployment, e.g.
103+
```
104+
export APIGW_ENDPOINT=https://xxxxx.apigateway.us-phoenix-1.oci.customer-oci.com/v1
105+
```
106+
107+
Use the curl command to make the HTTP request. You can optionally specify a request header just to see it returned by the function. You may want to pipe the curl command to `jq` to get a nicer output.
108+
```
109+
curl --header "X-MyHeader1: headerValue" $APIGW_ENDPOINT/display-httprequest-info | jq .
110+
```
111+
112+
Upon success, curl should return something similar to:
113+
```
114+
{
115+
"Headers": {
116+
"host": [
117+
"localhost",
118+
"xxxxx.apigateway.us-phoenix-1.oci.customer-oci.com"
119+
],
120+
"user-agent": [
121+
"lua-resty-http/0.14 (Lua) ngx_lua/10015",
122+
"curl/7.64.1"
123+
],
124+
"transfer-encoding": "chunked",
125+
"content-type": [
126+
"application/octet-stream",
127+
"application/octet-stream"
128+
],
129+
"date": "2020年6月23日 01:09:41 GMT",
130+
"fn-call-id": "xxxxxxxxx",
131+
"fn-deadline": "2020年06月23日T01:10:21Z",
132+
"accept": "*/*",
133+
"forwarded": "for=x.x.x.x",
134+
"x-forwarded-for": "x.x.x.x",
135+
"x-myheader1": "headerValue",
136+
"x-real-ip": "x.x.x.x",
137+
"fn-http-method": "GET",
138+
"fn-http-request-url": "/v1/display-httprequest-info",
139+
"fn-intent": "httprequest",
140+
"fn-invoke-type": "sync",
141+
"oci-subject-id": "ocid1.apigateway.oc1.phx.xxxxx",
142+
"oci-subject-tenancy-id": "ocid1.tenancy.oc1..xxxxx",
143+
"oci-subject-type": "resource",
144+
"opc-request-id": "xxxxxxxxx",
145+
"x-content-sha256": "xxxxxxxxx",
146+
"accept-encoding": "gzip"
147+
},
148+
"Configuration": {
149+
"PATH": "/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
150+
"HOSTNAME": "xxxxxxxxx",
151+
"FN_FN_ID": "ocid1.fnfunc.oc1.phx.xxxxx",
152+
"FN_MEMORY": "256",
153+
"FN_TYPE": "sync",
154+
"configkey1": "value1",
155+
"FN_LISTENER": "unix:/tmp/iofs/lsnr.sock",
156+
"FN_FORMAT": "http-stream",
157+
"FN_APP_ID": "ocid1.fnapp.oc1.phx.xxxxx",
158+
"FN_CPUS": "100m",
159+
"OCI_RESOURCE_PRINCIPAL_RPST": "/.oci-credentials/rpst",
160+
"OCI_RESOURCE_PRINCIPAL_PRIVATE_PEM": "/.oci-credentials/private.pem",
161+
"OCI_RESOURCE_PRINCIPAL_VERSION": "2.2",
162+
"OCI_RESOURCE_PRINCIPAL_REGION": "us-phoenix-1",
163+
"OCI_REGION_METADATA": "{\"realmDomainComponent\":\"oraclecloud.com\",\"realmKey\":\"ocX\",\"regionIdentifier\":\"xx-xxxxx-x\",\"regionKey\":\"XXX\"}",
164+
"LANG": "C.UTF-8",
165+
"GPG_KEY": "xxxxxxxxx",
166+
"PYTHON_VERSION": "3.6.10",
167+
"PYTHON_PIP_VERSION": "20.1.1",
168+
"PYTHON_GET_PIP_URL": "https://github.com/pypa/get-pip/raw/eff16c878c7fd6b688b9b4c4267695cf1a0bf01b/get-pip.py",
169+
"PYTHON_GET_PIP_SHA256": "xxxxxxxxx",
170+
"PYTHONPATH": "/function:/python",
171+
"HOME": "/home/fn"
172+
},
173+
"Request body": {},
174+
"Request URL": "/v1/display-httprequest-info",
175+
"Query String": {},
176+
"Request Method": "GET",
177+
"AppID": "ocid1.fnapp.oc1.phx.xxxxx",
178+
"FnID": "ocid1.fnfunc.oc1.phx.xxxxx",
179+
"CallID": "xxxxxxxxx",
180+
"Format": "http-stream",
181+
"Deadline": "2020年06月23日T01:10:21Z"
182+
}
183+
```
184+
185+
Now, use the "POST" method so you can specify a request payload, and specify some query string parameters:
186+
```
187+
curl -X POST --header "X-MyHeader1: headerValue" -d '{"key1":"value"}' "$APIGW_ENDPOINT/display-httprequest-info?key1=value1&key2=value2" | jq .
188+
```
189+
190+
Upon success, curl should return something similar to:
191+
```
192+
{
193+
"Headers": {
194+
"host": [
195+
"localhost",
196+
"xxxxx.apigateway.us-phoenix-1.oci.customer-oci.com"
197+
],
198+
"user-agent": [
199+
"lua-resty-http/0.14 (Lua) ngx_lua/10015",
200+
"curl/7.64.1"
201+
],
202+
"transfer-encoding": "chunked",
203+
"content-type": [
204+
"application/x-www-form-urlencoded",
205+
"application/x-www-form-urlencoded"
206+
],
207+
"date": "2020年6月23日 17:58:40 GMT",
208+
"fn-call-id": "xxxxxxxxx",
209+
"fn-deadline": "2020年06月23日T17:59:10Z",
210+
"accept": "*/*",
211+
"content-length": "16",
212+
"forwarded": "for=x.x.x.x",
213+
"x-forwarded-for": "x.x.x.x",
214+
"x-myheader1": "headerValue",
215+
"x-real-ip": "x.x.x.x",
216+
"fn-http-method": "POST",
217+
"fn-http-request-url": "/v1/display-httprequest-info?key1=value1&key2=value2",
218+
"fn-intent": "httprequest",
219+
"fn-invoke-type": "sync",
220+
"oci-subject-id": "ocid1.apigateway.oc1.phx.xxxxx",
221+
"oci-subject-tenancy-id": "ocid1.tenancy.oc1..xxxxx",
222+
"oci-subject-type": "resource",
223+
"opc-request-id": "xxxxxxxxx",
224+
"x-content-sha256": "xxxxxxxxx",
225+
"accept-encoding": "gzip"
226+
},
227+
"Configuration": {
228+
"PATH": "/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
229+
"HOSTNAME": "xxxxxxxxx",
230+
"FN_LISTENER": "unix:/tmp/iofs/lsnr.sock",
231+
"FN_FORMAT": "http-stream",
232+
"FN_APP_ID": "ocid1.fnapp.oc1.phx.xxxxx",
233+
"FN_CPUS": "100m",
234+
"FN_FN_ID": "ocid1.fnfunc.oc1.phx.xxxxx",
235+
"FN_MEMORY": "256",
236+
"FN_TYPE": "sync",
237+
"configkey1": "value1",
238+
"OCI_RESOURCE_PRINCIPAL_RPST": "/.oci-credentials/rpst",
239+
"OCI_RESOURCE_PRINCIPAL_PRIVATE_PEM": "/.oci-credentials/private.pem",
240+
"OCI_RESOURCE_PRINCIPAL_VERSION": "2.2",
241+
"OCI_RESOURCE_PRINCIPAL_REGION": "us-phoenix-1",
242+
"OCI_REGION_METADATA": "{\"realmDomainComponent\":\"oraclecloud.com\",\"realmKey\":\"ocX\",\"regionIdentifier\":\"xx-xxxxx-x\",\"regionKey\":\"XXX\"}",
243+
"LANG": "C.UTF-8",
244+
"GPG_KEY": "xxxxxxxxx",
245+
"PYTHON_VERSION": "3.6.10",
246+
"PYTHON_PIP_VERSION": "20.1.1",
247+
"PYTHON_GET_PIP_URL": "https://github.com/pypa/get-pip/raw/eff16c878c7fd6b688b9b4c4267695cf1a0bf01b/get-pip.py",
248+
"PYTHON_GET_PIP_SHA256": "xxxxxxxxx",
249+
"PYTHONPATH": "/function:/python",
250+
"HOME": "/home/fn"
251+
},
252+
"Request body": {
253+
"key1": "value"
254+
},
255+
"Request URL": "/v1/display-httprequest-info?key1=value1&key2=value2",
256+
"Query String": {
257+
"key1": [
258+
"value1"
259+
],
260+
"key2": [
261+
"value2"
262+
]
263+
},
264+
"Request Method": "POST",
265+
"AppID": "ocid1.fnapp.oc1.phx.xxxxx",
266+
"FnID": "ocid1.fnfunc.oc1.phx.xxxxx",
267+
"CallID": "xxxxxxxxx",
268+
"Format": "http-stream",
269+
"Deadline": "2020年06月23日T17:59:10Z"
270+
}
271+
```
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#
2+
# oci-apigw-display-httprequest-info-python version 1.0.
3+
#
4+
# Copyright (c) 2020 Oracle, Inc.
5+
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
6+
#
7+
8+
import io
9+
import json
10+
import oci
11+
import logging
12+
from urllib.parse import urlparse, parse_qs
13+
14+
from fdk import response
15+
16+
17+
def handler(ctx, data: io.BytesIO=None):
18+
logging.getLogger().info("function handler start")
19+
20+
resp = {}
21+
22+
# retrieving the request headers
23+
headers = ctx.Headers()
24+
logging.getLogger().info("Headers: " + json.dumps(headers))
25+
resp["Headers"] = headers
26+
27+
# retrieving the function configuration
28+
resp["Configuration"] = dict(ctx.Config())
29+
logging.getLogger().info("Configuration: " + json.dumps(resp["Configuration"]))
30+
31+
# retrieving the request body, e.g. {"key1":"value"}
32+
#requestbody_bytes = data.getvalue()
33+
#if requestbody_bytes==b'':
34+
# logging.getLogger().info("No request body")
35+
# requestbody = {}
36+
#else:
37+
# requestbody = json.loads(requestbody_bytes)
38+
# logging.getLogger().info()
39+
try:
40+
requestbody_str = data.getvalue().decode('UTF-8')
41+
if requestbody_str:
42+
resp["Request body"] = json.loads(requestbody_str)
43+
else:
44+
resp["Request body"] = {}
45+
except Exception as ex:
46+
print('ERROR: The request body is not JSON', ex, flush=True)
47+
raise
48+
49+
# retrieving the request URL, e.g. "/v1/display-uri-info"
50+
requesturl = ctx.RequestURL()
51+
logging.getLogger().info("Request URL: " + json.dumps(requesturl))
52+
resp["Request URL"] = requesturl
53+
54+
# retrieving query string from the request URL, e.g. {"param1":["value"]}
55+
parsed_url = urlparse(requesturl)
56+
resp["Query String"] = parse_qs(parsed_url.query)
57+
logging.getLogger().info("Query string: " + json.dumps(resp["Query String"]))
58+
59+
# retrieving the request method, e.g. "POST", "GET"...
60+
method = ctx.Method()
61+
if method:
62+
logging.getLogger().info("Request Method: " + method)
63+
resp["Request Method"] = method
64+
else:
65+
logging.getLogger().info("No Request Method")
66+
resp["Request Method"] = None
67+
68+
# retrieving the Application ID, e.g. "ocid1.fnapp.oc1.phx.aaaaxxxx"
69+
appid = ctx.AppID()
70+
logging.getLogger().info("AppID: " + appid)
71+
resp["AppID"] = appid
72+
73+
# retrieving the Function ID, e.g. "ocid1.fnfunc.oc1.phx.aaaaxxxxx"
74+
fnid = ctx.FnID()
75+
logging.getLogger().info("FnID: " + fnid)
76+
resp["FnID"] = fnid
77+
78+
# retrieving the Function call ID, e.g. "01E9FE6JBW1BT0C68ZJ003KR1Q"
79+
callid = ctx.CallID()
80+
logging.getLogger().info("CallID: " + callid)
81+
resp["CallID"] = callid
82+
83+
# retrieving the Function format, e.g. "http-stream"
84+
fnformat = ctx.Format()
85+
logging.getLogger().info("Format: " + fnformat)
86+
resp["Format"] = fnformat
87+
88+
# retrieving the Function deadline, e.g. "2020年05月29日T05:24:46Z"
89+
deadline = ctx.Deadline()
90+
logging.getLogger().info("Deadline: " + deadline)
91+
resp["Deadline"] = deadline
92+
93+
logging.getLogger().info("function handler end")
94+
return response.Response(
95+
ctx,
96+
response_data=json.dumps(resp),
97+
headers={"Content-Type": "application/json"}
98+
)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
schema_version: 20180708
2+
name: oci-apigw-display-httprequest-info-python
3+
version: 0.0.8
4+
runtime: python
5+
entrypoint: /python/bin/fdk /function/func.py handler
6+
memory: 256
135 KB
Loading[フレーム]
103 KB
Loading[フレーム]
41.5 KB
Loading[フレーム]
2.96 KB
Loading[フレーム]
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
fdk
2+
oci

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /