rest
This commit is contained in:
commit
71dd0a607a
125
README.md
Normal file
125
README.md
Normal file
@ -0,0 +1,125 @@
|
||||
## AWS REST Web Service
|
||||
|
||||
Instrukcja uruchomienia web serwisu RESTowego na platformie AWS przy użyciu `AWS Lambda`, `API Gateway` oraz `DynamoDB`:
|
||||
|
||||
1. Utwórz tabelę w `DynamoDB`:
|
||||
- Przejdź do konsoli AWS i wybierz usługę `DynamoDB`.
|
||||
- Kliknij przycisk `Create table`.
|
||||
- Wprowadź nazwę tabeli: `Posts`.
|
||||
- Wprowadź klucz główny: `id` typu `String`.
|
||||
- Kliknij przycisk `Create`.
|
||||
|
||||
2. Utwórz funkcję w `AWS Lambda` do obsługi żądań `CRUD`:
|
||||
- Przejdź do konsoli AWS i wybierz usługę `Lambda`.
|
||||
- Kliknij przycisk `Create function`.
|
||||
- Wybierz opcję `Author from scratch`.
|
||||
- Wprowadź nazwę funkcji, np. `postsCRUD`.
|
||||
- Wybierz runtime, np. `Python 3.13`.
|
||||
- W sekcji `Change default execution role` wybierz opcję `Use an existing role` i wybierz rolę `LabRole`.
|
||||
- Kliknij przycisk `Create function`.
|
||||
- Wklej poniższy kod do edytora funkcji:
|
||||
```python
|
||||
import json
|
||||
import boto3
|
||||
from decimal import Decimal
|
||||
|
||||
dynamodb = boto3.resource("dynamodb")
|
||||
table = dynamodb.Table('Posts')
|
||||
|
||||
|
||||
def lambda_handler(event, context):
|
||||
print(event)
|
||||
body = {}
|
||||
statusCode = 200
|
||||
|
||||
try:
|
||||
# Endpoint: DELETE /posts/{id}
|
||||
if event['routeKey'] == "DELETE /posts/{id}":
|
||||
table.delete_item(
|
||||
Key={'id': event['pathParameters']['id']}
|
||||
)
|
||||
body = {"message": f"Deleted item with id {event['pathParameters']['id']}"}
|
||||
|
||||
# Endpoint: GET /posts/{id}
|
||||
elif event['routeKey'] == "GET /posts/{id}":
|
||||
response = table.get_item(
|
||||
Key={'id': event['pathParameters']['id']}
|
||||
)
|
||||
if 'Item' in response:
|
||||
body = response['Item']
|
||||
else:
|
||||
statusCode = 404
|
||||
body = {"error": "Item not found"}
|
||||
|
||||
# Endpoint: GET /posts
|
||||
elif event['routeKey'] == "GET /posts":
|
||||
response = table.scan()
|
||||
items = response.get('Items', [])
|
||||
body = items
|
||||
|
||||
# Endpoint: POST /posts
|
||||
elif event['routeKey'] == "POST /posts":
|
||||
requestJSON = json.loads(event['body'])
|
||||
table.put_item(
|
||||
Item={
|
||||
'id': str(requestJSON['id']), # DynamoDB keys must be strings
|
||||
'userId': str(requestJSON['userId']),
|
||||
'title': requestJSON['title'],
|
||||
'body': requestJSON['body']
|
||||
}
|
||||
)
|
||||
body = {"message": f"Created item with id {requestJSON['id']}"}
|
||||
|
||||
# Endpoint: PUT /posts/{id}
|
||||
elif event['routeKey'] == "PUT /posts/{id}":
|
||||
requestJSON = json.loads(event['body'])
|
||||
table.update_item(
|
||||
Key={'id': event['pathParameters']['id']},
|
||||
UpdateExpression="SET userId = :userId, title = :title, body = :body",
|
||||
ExpressionAttributeValues={
|
||||
':userId': str(requestJSON['userId']),
|
||||
':title': requestJSON['title'],
|
||||
':body': requestJSON['body']
|
||||
}
|
||||
)
|
||||
body = {"message": f"Updated item with id {event['pathParameters']['id']}"}
|
||||
|
||||
# Unsupported route
|
||||
else:
|
||||
statusCode = 400
|
||||
body = {"error": f"Unsupported route: {event['routeKey']}"}
|
||||
|
||||
except Exception as e:
|
||||
statusCode = 500
|
||||
body = {"error": str(e)}
|
||||
|
||||
# Return the response
|
||||
return {
|
||||
"statusCode": statusCode,
|
||||
"headers": {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
"body": json.dumps(body)
|
||||
}
|
||||
```
|
||||
|
||||
3. Utwórz HTTP API w `API Gateway` do przekierowywania żądań do funkcji `AWS Lambda`:
|
||||
- Przejdź do konsoli AWS i wybierz usługę `API Gateway`.
|
||||
- Kliknij przycisk `Create API`.
|
||||
- Wybierz opcję `HTTP API`.
|
||||
- Wprowadź nazwę API, np. `PostsAPI`.
|
||||
- Przejdź przez formularz i utwórz API.
|
||||
- Utwórz endpointy dla żądań `GET`, `POST`, `PUT` i `DELETE`, np.:
|
||||
```
|
||||
GET /posts
|
||||
GET /posts/{id}
|
||||
POST /posts
|
||||
PUT /posts/{id}
|
||||
DELETE /posts/{id}
|
||||
```
|
||||
- Utwórz i przypisz integrację z funkcją `AWS Lambda` dla każdego endpointu.
|
||||
|
||||
4. I gotowe. Możesz teraz uruchomić skrypt testowy `test.ipynb` do testowania web serwisu RESTowego. Pamiętaj, by zmienić adres URL API w skrypcie na Twój adres URL.
|
||||
|
||||
### Materiały
|
||||
* https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-dynamo-db.html#http-api-dynamo-db-create-table
|
107
test.ipynb
Normal file
107
test.ipynb
Normal file
@ -0,0 +1,107 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"id": "initial_id",
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-12-22T20:11:38.991267Z",
|
||||
"start_time": "2024-12-22T20:11:31.288506Z"
|
||||
}
|
||||
},
|
||||
"source": [
|
||||
"WEBSERVICE_URL = \"https://z309w7i8t3.execute-api.us-east-1.amazonaws.com/posts\"\n",
|
||||
"\n",
|
||||
"import requests\n",
|
||||
"from faker import Faker\n",
|
||||
"fake = Faker()\n",
|
||||
"\n",
|
||||
"n = 3\n",
|
||||
"\n",
|
||||
"outs = []\n",
|
||||
"outs2 = []\n",
|
||||
"\n",
|
||||
"OK = True\n",
|
||||
"\n",
|
||||
"for i in range(n):\n",
|
||||
" try:\n",
|
||||
" outs.append(requests.post(WEBSERVICE_URL, json={'userId': 1, 'title': fake.catch_phrase(), 'body': fake.text()}).json())\n",
|
||||
" except:\n",
|
||||
" print(\"Nie udało się dodać nowego zasobu\")\n",
|
||||
" OK = False\n",
|
||||
"\n",
|
||||
"for i in range(n):\n",
|
||||
" try:\n",
|
||||
" tmp = requests.get(WEBSERVICE_URL+'/'+str(outs[i]['id'])).json()\n",
|
||||
" if tmp != outs[i]:\n",
|
||||
" print(\"Pobrany zasób nie jest zgodny ze wzrocem\")\n",
|
||||
" OK = False\n",
|
||||
" except:\n",
|
||||
" print(\"Nie udało się pobrać zasobu: \"+WEBSERVICE_URL+'/'+str(outs[i]['id']))\n",
|
||||
" OK = False\n",
|
||||
"\n",
|
||||
"for i in range(n):\n",
|
||||
" try:\n",
|
||||
" outs2.append(requests.put(WEBSERVICE_URL+'/'+str(outs[i]['id']), json={'userId': 1, 'title': fake.catch_phrase(), 'body': fake.text()}).json())\n",
|
||||
" except:\n",
|
||||
" OK = False\n",
|
||||
" print(\"Nie udało się zmodyfikować zasobu: \"+WEBSERVICE_URL+'/'+str(outs[i]['id']))\n",
|
||||
"\n",
|
||||
"for i in range(n):\n",
|
||||
" try:\n",
|
||||
" tmp = requests.get(WEBSERVICE_URL+'/'+str(outs[i]['id'])).json()\n",
|
||||
" if tmp != outs2[i]:\n",
|
||||
" print(\"Pobrany zasób nie jest zgodny ze zaktualizowanym wzrocem\")\n",
|
||||
" OK = False\n",
|
||||
" except:\n",
|
||||
" print(\"Nie udało się pobrać zasobu: \"+WEBSERVICE_URL+'/'+str(outs[i]['id']))\n",
|
||||
" OK = False\n",
|
||||
"\n",
|
||||
"for i in range(n):\n",
|
||||
" try:\n",
|
||||
" requests.delete(WEBSERVICE_URL+'/'+str(outs[i]['id']), data={'userId': 1, 'title': fake.catch_phrase(), 'body': fake.text()}).json()\n",
|
||||
" except:\n",
|
||||
" print(\"Nie udało się usunąć zasobu: \"+WEBSERVICE_URL+'/'+str(outs[i]['id']))\n",
|
||||
" OK = False\n",
|
||||
"\n",
|
||||
"if OK:\n",
|
||||
" print(\"==================\\nOK zaliczone\")\n",
|
||||
"else:\n",
|
||||
" print(\"==================\\nNie zaliczone\")"
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"==================\n",
|
||||
"OK zaliczone\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"execution_count": 15
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.6"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
Loading…
Reference in New Issue
Block a user