From 71dd0a607a1e047a186254a03c9ff3385eef9635 Mon Sep 17 00:00:00 2001 From: dzikafoczka Date: Sun, 22 Dec 2024 21:11:54 +0100 Subject: [PATCH] rest --- README.md | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++++ test.ipynb | 107 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 232 insertions(+) create mode 100644 README.md create mode 100644 test.ipynb diff --git a/README.md b/README.md new file mode 100644 index 0000000..efdfdd6 --- /dev/null +++ b/README.md @@ -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 \ No newline at end of file diff --git a/test.ipynb b/test.ipynb new file mode 100644 index 0000000..9fcef1a --- /dev/null +++ b/test.ipynb @@ -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 +}