Amazon API Gateway and AWS Lambda are semi-automatically clicked from the CLI. It seems that you can make it. I like AWS Lambda (and Amazon API Gateway) so I touched it.
It is recommended to create a virtual environment with AWS Chalice Hands-on, so create it as needed. I will.
$ pip install virtualenv
# 『~/.virtualenvs/chalice-"handson" is the environment name
#It's just for AWS hands-on, so you can use any environment name.
virtualenv ~/.virtualenvs/chalice-handson
$ source ~/.virtualenvs/chalice-handson/bin/activate
#"Source" is ".] Can be substituted, so the following command has the same meaning as above.
$ . ~/.virtualenvs/chalice-handson/bin/activate
If you want to terminate the virtual environment, use the following command. Even if you exit the virtual environment, the created virtual environment file remains, so you can enter the virtual environment by typing the enable command again.
$ deactivate
$ pip install chalice
#Check if it was installed
$ chalice --version
chalice 1.12.0, python 3.7.3, darwin 19.6.0
If ~ / .aws / credentials
and ~ / .aws / config
do not exist, set them with the following command.
Otherwise you will get angry when deploying to AWS.
$ aws configure
Now that we're ready, let's take a quick look at the flow from project creation to deployment to AWS. First, create a project with the following command.
#"Helloworld" is the project name used in AWS hands-on, and any project name can be specified.
$ chalice new-project helloworld
The following files are created by creating a project.
.
├── .chalice
│ └── config.json
├── .gitignore
├── app.py
└── requirements.txt
The contents of the automatically created ʻapp.py` are as follows. The content is simple, it returns {'hello':'world'} as a response body when accessing the index of the API Gateway endpoint. The response body {'hello':'world'} is set with {'hello':'world'} even if the project name is not helloworld.
from chalice import Chalice
app = Chalice(app_name = 'helloworld')
@app.route('/')
def index():
return {'hello': 'world'} #Even if the project name is other than helloworld, here{'hello': 'world'}is
Try it in your local environment to see if it actually behaves as described above (does it return {'hello':'world'} when accessed)? You can start the local server with the following command. : + 1: Easy and nice!
$ chalice local
Serving on http://127.0.0.1:8000
If you try to access it with a browser, you should see {"hello ":" world "}
.
It looks okay, so let's deploy it to AWS so that it can be accessed from outside. Deploying is easy, just run the following command.
$ chalice deploy
Then, the following will be created automatically on AWS.
--IAM roll --Lambda function
After deploying, the configuration will be as follows.
.
├── .chalice
│ ├── config.json
│ ├── deployed
│ │ └── dev.json
│ └── deployments
│ └── xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-python3.8.zip
├── .gitignore
├── app.py
└── requirements.txt
Finally, the API Gateway endpoint is displayed as Rest API URL
, so let's access it with a browser.
If you don't know the Rest API URL, you can display it with the following command.
$ chalice url
Now that you've seen the basics of using AWS Chalice, let's look at some more control features.
Parameters can be described in the path pattern of @ app.route ('/')
of ʻapp.py` as shown below, and the value received as a parameter can be used as an argument in the method.
from chalice import Chalice
app = Chalice(app_name = 'helloworld')
@app.route('/')
def index():
return {'hello': 'world'}
#Add the following
@app.route('/hello/{name}')
def greet(name):
return {'hello': name}
After editing ʻapp.py, do
chalice deployagain. After the deployment is complete, add
/ hello /" arbitrary value "to the API Gateway endpoint and access it with a browser. You should see
{" hello ":" "arbitrary value" "}`.
Please note that the value passed as "arbitrary value" is a character string even if it is a numerical value.
HTTP method can be specified by writing the method in @ app.route ('/')
of ʻapp.py` as follows.
from chalice import Chalice
app = Chalice(app_name = 'helloworld')
@app.route('/')
def index():
return {'hello': 'world'}
@app.route('/hello/{name}')
def greet(name):
return {'hello': name}
#Add the following
@app.route('/hello', methods = ['POST'])
def hello():
return {'hello': 'POST world'}
After editing ʻapp.py, do
chalice deploy` again.
The POST added this time cannot be confirmed from the browser, so let's check it quickly in Python's interactive mode.
$ python
>>> import requests #If requests are not included, pip install requests
>>> response = requests.post('"API Gateway Endpoint"/hello', data = {})
>>> print(response.text)
{"hello":"POST world"}
The code from here will only describe the change block and response. Metadata acquisition is specified in the form of ʻapp.current_request." Honyara "`. HTTP Method
@app.route('/hello')
def hello():
return {'metadata': app.current_request.method}
#response
{"metadata":"GET"}
Query Parameters
@app.route('/hello')
def hello():
return {'metadata': app.current_request.query_params}
#Response (request is/hello?test1=abc&test2=123&test2=456)
#If a parameter with the same name is specified in the request, chalice will win second (test2)=123&test2=456 is test2=Become 456)
{"metadata":{"test1":"abc","test2":"456"}}
Request Body - Raw
Get the request body in byte type.
If Content-Type: application / json
, you can use ʻapp.current_request.json_body instead of ʻapp.current_request.raw_body
. This is a character string type.
@app.route('/hello')
def hello():
return {'metadata': app.current_request.raw_body}
#request
$ python
>>> import requests, json
>>> response = requests.post('"API Gateway Endpoint"/hello', data = json.dumps({'hello': 'world'}), headers = {'Content-Type': 'application/json' })
>>> print(response.text)
#response
{"metadata":{"hello":"world"}}
Next, let's look at the response.
If you want to return an arbitrary status code or header, return it with arbitrary information included in the response class object.
Don't forget ʻimport Response. (It doesn't matter, but I wrote
json.dumps without
json.dumpand
s, and
{“Code”: “InternalServerError”, “Message”: “An internal server error occurred.”} I got a response of `and I was addicted to it for a while without noticing the mistake ...: persevere :)
from chalice import Chalice, Response
import json
app = Chalice(app_name='helloworld')
@app.route('/')
def index():
return Response(
body = json.dumps({'hello':'world'}),
headers = {'Content-Type': 'application/json'},
status_code = 200
)
@app.route('/text')
def text():
return Response(
body = 'Hello, World',
headers = {'Content-Type': 'text/plain'},
status_code = 200
)
Since there is a class for returning an error response, we will use it. The example below is a 403 Forbidden Error. Don't forget to import the error class here as well.
from chalice import Chalice, ForbiddenError
app = Chalice(app_name='helloworld')
@app.route('/forbidden')
def forbidden():
raise ForbiddenError(
'403!'
)
There are other error classes as follows. ([[Learn AWS with Easy Hands-on] Build a Serverless RESTful API! Python App Development Realized with Chalice | AWS Startup Blog](https://aws.amazon.com/jp/blogs/startup/event] See -report-chalice-handson /)) It is also possible to return a response with an error code that is not prepared by using the custom HTTP response introduced above. (Of course, it is also possible to return an error with an error code in a custom HTTP response.)
You can simply write the following.
@app.route('/', methods = ['POST'], cors = True)
I've always written it in the form of @ app.route ('/')
, but this is in the form of API Gateway + AWS Lambda.
AWS Lambda integration other than API Gateway is possible by using other decorators.
The following are currently supported.
--Independent AWS Lambda: @ app.lambda_function
@app.schedule
@app.on_s3_event
@app.on_sqs_message
@app.on_sns_message
For detailed usage and sample code, I tried to manage Lambda (Python) and API Gateway with Chalice is very helpful.
IAM roles, Lambda, and API Gateway (for @ app.route) deployed on AWS with chalice deploy
can be deleted in bulk with the following command.
$ chalice delete
It seems that you can build a serverless environment quite easily using AWS Chalice. It's easy to delete, so it's nice to be able to easily create and delete it. I was thinking of writing a more concrete example, but since it has already become a long article, I will summarize it in another article.
We're hiring! We are developing an AI chatbot. If you are interested, please feel free to contact us from the Wantedly page!
Recommended Posts