diff --git a/fruit_api.log b/fruit_api.log index 0f7ceab..ed2ffc7 100644 --- a/fruit_api.log +++ b/fruit_api.log @@ -127,3 +127,208 @@ 2025-09-29 19:55:02,233 [INFO] REQUEST: method=GET path=/fruits args={} body=None ip=127.0.0.1 2025-09-29 19:55:02,233 [INFO] RESPONSE: method=GET path=/fruits status=200 ip=127.0.0.1 2025-09-29 19:55:02,234 [INFO] 127.0.0.1 - - [29/Sep/2025 19:55:02] "GET /fruits HTTP/1.1" 200 - +2025-09-30 22:47:38,977 [INFO] WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on all addresses (0.0.0.0) + * Running on http://127.0.0.1:5000 + * Running on http://192.168.43.139:5000 +2025-09-30 22:47:39,008 [INFO] Press CTRL+C to quit +2025-09-30 22:47:56,131 [INFO] REQUEST: method=GET path=/health args={} body=None ip=127.0.0.1 +2025-09-30 22:47:56,132 [INFO] RESPONSE: method=GET path=/health status=200 ip=127.0.0.1 +2025-09-30 22:47:56,133 [INFO] 127.0.0.1 - - [30/Sep/2025 22:47:56] "GET /health HTTP/1.1" 200 - +2025-09-30 22:47:56,188 [INFO] REQUEST: method=GET path=/fruits args={} body=None ip=127.0.0.1 +2025-09-30 22:47:56,189 [INFO] RESPONSE: method=GET path=/fruits status=200 ip=127.0.0.1 +2025-09-30 22:47:56,189 [INFO] 127.0.0.1 - - [30/Sep/2025 22:47:56] "GET /fruits HTTP/1.1" 200 - +2025-09-30 22:47:56,232 [INFO] REQUEST: method=GET path=/fruits/1 args={} body=None ip=127.0.0.1 +2025-09-30 22:47:56,233 [INFO] RESPONSE: method=GET path=/fruits/1 status=200 ip=127.0.0.1 +2025-09-30 22:47:56,234 [INFO] 127.0.0.1 - - [30/Sep/2025 22:47:56] "GET /fruits/1 HTTP/1.1" 200 - +2025-09-30 22:47:56,301 [INFO] REQUEST: method=POST path=/fruits args={} body={'name': 'Mango', 'color': 'Yellow', 'price': 2.5, 'quantity': 50, 'category': 'Tropical'} ip=127.0.0.1 +2025-09-30 22:47:56,302 [INFO] RESPONSE: method=POST path=/fruits status=201 ip=127.0.0.1 +2025-09-30 22:47:56,302 [INFO] 127.0.0.1 - - [30/Sep/2025 22:47:56] "POST /fruits HTTP/1.1" 201 - +2025-09-30 22:47:56,326 [INFO] REQUEST: method=PUT path=/fruits/1 args={} body={'name': 'Green Apple', 'price': 1.8} ip=127.0.0.1 +2025-09-30 22:47:56,327 [INFO] RESPONSE: method=PUT path=/fruits/1 status=405 ip=127.0.0.1 +2025-09-30 22:47:56,327 [INFO] 127.0.0.1 - - [30/Sep/2025 22:47:56] "PUT /fruits/1 HTTP/1.1" 405 - +2025-09-30 22:47:56,351 [INFO] REQUEST: method=DELETE path=/fruits/1 args={} body=None ip=127.0.0.1 +2025-09-30 22:47:56,352 [INFO] RESPONSE: method=DELETE path=/fruits/1 status=405 ip=127.0.0.1 +2025-09-30 22:47:56,352 [INFO] 127.0.0.1 - - [30/Sep/2025 22:47:56] "DELETE /fruits/1 HTTP/1.1" 405 - +2025-09-30 22:47:56,376 [INFO] REQUEST: method=GET path=/fruits/search args={'name': 'apple'} body=None ip=127.0.0.1 +2025-09-30 22:47:56,377 [INFO] RESPONSE: method=GET path=/fruits/search status=404 ip=127.0.0.1 +2025-09-30 22:47:56,377 [INFO] 127.0.0.1 - - [30/Sep/2025 22:47:56] "GET /fruits/search?name=apple HTTP/1.1" 404 - +2025-09-30 22:47:56,403 [INFO] REQUEST: method=GET path=/fruits/category/Tropical args={} body=None ip=127.0.0.1 +2025-09-30 22:47:56,403 [INFO] RESPONSE: method=GET path=/fruits/category/Tropical status=404 ip=127.0.0.1 +2025-09-30 22:47:56,404 [INFO] 127.0.0.1 - - [30/Sep/2025 22:47:56] "GET /fruits/category/Tropical HTTP/1.1" 404 - +2025-09-30 22:48:14,383 [INFO] REQUEST: method=GET path=/health args={} body=None ip=127.0.0.1 +2025-09-30 22:48:14,383 [INFO] RESPONSE: method=GET path=/health status=200 ip=127.0.0.1 +2025-09-30 22:48:14,384 [INFO] 127.0.0.1 - - [30/Sep/2025 22:48:14] "GET /health HTTP/1.1" 200 - +2025-09-30 22:48:14,435 [INFO] REQUEST: method=GET path=/fruits args={} body=None ip=127.0.0.1 +2025-09-30 22:48:14,436 [INFO] RESPONSE: method=GET path=/fruits status=200 ip=127.0.0.1 +2025-09-30 22:48:14,437 [INFO] 127.0.0.1 - - [30/Sep/2025 22:48:14] "GET /fruits HTTP/1.1" 200 - +2025-09-30 22:48:14,484 [INFO] REQUEST: method=GET path=/fruits/1 args={} body=None ip=127.0.0.1 +2025-09-30 22:48:14,484 [INFO] RESPONSE: method=GET path=/fruits/1 status=200 ip=127.0.0.1 +2025-09-30 22:48:14,485 [INFO] 127.0.0.1 - - [30/Sep/2025 22:48:14] "GET /fruits/1 HTTP/1.1" 200 - +2025-09-30 22:48:14,533 [INFO] REQUEST: method=POST path=/fruits args={} body={'name': 'Mango', 'color': 'Yellow', 'price': 2.5, 'quantity': 50, 'category': 'Tropical'} ip=127.0.0.1 +2025-09-30 22:48:14,534 [INFO] RESPONSE: method=POST path=/fruits status=201 ip=127.0.0.1 +2025-09-30 22:48:14,536 [INFO] 127.0.0.1 - - [30/Sep/2025 22:48:14] "POST /fruits HTTP/1.1" 201 - +2025-09-30 22:48:14,595 [INFO] REQUEST: method=PUT path=/fruits/1 args={} body={'name': 'Green Apple', 'price': 1.8} ip=127.0.0.1 +2025-09-30 22:48:14,596 [INFO] RESPONSE: method=PUT path=/fruits/1 status=405 ip=127.0.0.1 +2025-09-30 22:48:14,596 [INFO] 127.0.0.1 - - [30/Sep/2025 22:48:14] "PUT /fruits/1 HTTP/1.1" 405 - +2025-09-30 22:48:14,648 [INFO] REQUEST: method=DELETE path=/fruits/1 args={} body=None ip=127.0.0.1 +2025-09-30 22:48:14,649 [INFO] RESPONSE: method=DELETE path=/fruits/1 status=405 ip=127.0.0.1 +2025-09-30 22:48:14,649 [INFO] 127.0.0.1 - - [30/Sep/2025 22:48:14] "DELETE /fruits/1 HTTP/1.1" 405 - +2025-09-30 22:48:14,669 [INFO] REQUEST: method=GET path=/fruits/search args={'name': 'apple'} body=None ip=127.0.0.1 +2025-09-30 22:48:14,669 [INFO] RESPONSE: method=GET path=/fruits/search status=404 ip=127.0.0.1 +2025-09-30 22:48:14,670 [INFO] 127.0.0.1 - - [30/Sep/2025 22:48:14] "GET /fruits/search?name=apple HTTP/1.1" 404 - +2025-09-30 22:48:14,684 [INFO] REQUEST: method=GET path=/fruits/category/Tropical args={} body=None ip=127.0.0.1 +2025-09-30 22:48:14,685 [INFO] RESPONSE: method=GET path=/fruits/category/Tropical status=404 ip=127.0.0.1 +2025-09-30 22:48:14,685 [INFO] 127.0.0.1 - - [30/Sep/2025 22:48:14] "GET /fruits/category/Tropical HTTP/1.1" 404 - +2025-09-30 22:48:28,832 [INFO] REQUEST: method=GET path=/health args={} body=None ip=127.0.0.1 +2025-09-30 22:48:28,832 [INFO] RESPONSE: method=GET path=/health status=200 ip=127.0.0.1 +2025-09-30 22:48:28,834 [INFO] 127.0.0.1 - - [30/Sep/2025 22:48:28] "GET /health HTTP/1.1" 200 - +2025-09-30 22:48:28,850 [INFO] REQUEST: method=GET path=/fruits args={} body=None ip=127.0.0.1 +2025-09-30 22:48:28,851 [INFO] RESPONSE: method=GET path=/fruits status=200 ip=127.0.0.1 +2025-09-30 22:48:28,851 [INFO] 127.0.0.1 - - [30/Sep/2025 22:48:28] "GET /fruits HTTP/1.1" 200 - +2025-09-30 22:48:28,873 [INFO] REQUEST: method=GET path=/fruits/1 args={} body=None ip=127.0.0.1 +2025-09-30 22:48:28,874 [INFO] RESPONSE: method=GET path=/fruits/1 status=200 ip=127.0.0.1 +2025-09-30 22:48:28,874 [INFO] 127.0.0.1 - - [30/Sep/2025 22:48:28] "GET /fruits/1 HTTP/1.1" 200 - +2025-09-30 22:48:28,893 [INFO] REQUEST: method=POST path=/fruits args={} body={'name': 'Mango', 'color': 'Yellow', 'price': 2.5, 'quantity': 50, 'category': 'Tropical'} ip=127.0.0.1 +2025-09-30 22:48:28,894 [INFO] RESPONSE: method=POST path=/fruits status=201 ip=127.0.0.1 +2025-09-30 22:48:28,895 [INFO] 127.0.0.1 - - [30/Sep/2025 22:48:28] "POST /fruits HTTP/1.1" 201 - +2025-09-30 22:48:28,914 [INFO] REQUEST: method=PUT path=/fruits/1 args={} body={'name': 'Green Apple', 'price': 1.8} ip=127.0.0.1 +2025-09-30 22:48:28,915 [INFO] RESPONSE: method=PUT path=/fruits/1 status=405 ip=127.0.0.1 +2025-09-30 22:48:28,915 [INFO] 127.0.0.1 - - [30/Sep/2025 22:48:28] "PUT /fruits/1 HTTP/1.1" 405 - +2025-09-30 22:48:28,939 [INFO] REQUEST: method=DELETE path=/fruits/1 args={} body=None ip=127.0.0.1 +2025-09-30 22:48:28,940 [INFO] RESPONSE: method=DELETE path=/fruits/1 status=405 ip=127.0.0.1 +2025-09-30 22:48:28,940 [INFO] 127.0.0.1 - - [30/Sep/2025 22:48:28] "DELETE /fruits/1 HTTP/1.1" 405 - +2025-09-30 22:48:28,960 [INFO] REQUEST: method=GET path=/fruits/search args={'name': 'apple'} body=None ip=127.0.0.1 +2025-09-30 22:48:28,960 [INFO] RESPONSE: method=GET path=/fruits/search status=404 ip=127.0.0.1 +2025-09-30 22:48:28,960 [INFO] 127.0.0.1 - - [30/Sep/2025 22:48:28] "GET /fruits/search?name=apple HTTP/1.1" 404 - +2025-09-30 22:48:28,977 [INFO] REQUEST: method=GET path=/fruits/category/Tropical args={} body=None ip=127.0.0.1 +2025-09-30 22:48:28,977 [INFO] RESPONSE: method=GET path=/fruits/category/Tropical status=404 ip=127.0.0.1 +2025-09-30 22:48:28,978 [INFO] 127.0.0.1 - - [30/Sep/2025 22:48:28] "GET /fruits/category/Tropical HTTP/1.1" 404 - +2025-09-30 22:53:33,909 - INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on all addresses (0.0.0.0) + * Running on http://127.0.0.1:5000 + * Running on http://192.168.43.139:5000 +2025-09-30 22:53:33,921 - INFO - Press CTRL+C to quit +2025-09-30 22:53:33,932 - INFO - * Restarting with stat +2025-09-30 22:53:34,272 - WARNING - * Debugger is active! +2025-09-30 22:53:34,288 - INFO - * Debugger PIN: 117-497-176 +2025-09-30 22:53:43,983 - INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on all addresses (0.0.0.0) + * Running on http://127.0.0.1:5000 + * Running on http://192.168.43.139:5000 +2025-09-30 22:53:43,985 - INFO - Press CTRL+C to quit +2025-09-30 22:53:43,986 - INFO - * Restarting with stat +2025-09-30 22:53:44,149 - WARNING - * Debugger is active! +2025-09-30 22:53:44,153 - INFO - * Debugger PIN: 117-497-176 +2025-09-30 22:53:52,705 - INFO - REQUEST: GET / - From 127.0.0.1 +2025-09-30 22:53:52,707 - INFO - RESPONSE: GET / - Status 200 +2025-09-30 22:53:52,708 - INFO - 127.0.0.1 - - [30/Sep/2025 22:53:52] "GET / HTTP/1.1" 200 - +2025-09-30 22:53:53,367 - INFO - REQUEST: GET /favicon.ico - From 127.0.0.1 +2025-09-30 22:53:53,367 - INFO - RESPONSE: GET /favicon.ico - Status 404 +2025-09-30 22:53:53,367 - INFO - 127.0.0.1 - - [30/Sep/2025 22:53:53] "GET /favicon.ico HTTP/1.1" 404 - +2025-09-30 22:54:01,228 - INFO - REQUEST: GET /health - From 127.0.0.1 +2025-09-30 22:54:01,228 - INFO - RESPONSE: GET /health - Status 200 +2025-09-30 22:54:01,229 - INFO - 127.0.0.1 - - [30/Sep/2025 22:54:01] "GET /health HTTP/1.1" 200 - +2025-09-30 22:54:01,275 - INFO - REQUEST: GET /fruits - From 127.0.0.1 +2025-09-30 22:54:01,275 - INFO - RESPONSE: GET /fruits - Status 200 +2025-09-30 22:54:01,276 - INFO - 127.0.0.1 - - [30/Sep/2025 22:54:01] "GET /fruits HTTP/1.1" 200 - +2025-09-30 22:54:01,332 - INFO - REQUEST: GET /fruits/1 - From 127.0.0.1 +2025-09-30 22:54:01,333 - INFO - RESPONSE: GET /fruits/1 - Status 200 +2025-09-30 22:54:01,334 - INFO - 127.0.0.1 - - [30/Sep/2025 22:54:01] "GET /fruits/1 HTTP/1.1" 200 - +2025-09-30 22:54:01,375 - INFO - REQUEST: POST /fruits - From 127.0.0.1 +2025-09-30 22:54:01,376 - INFO - RESPONSE: POST /fruits - Status 201 +2025-09-30 22:54:01,377 - INFO - 127.0.0.1 - - [30/Sep/2025 22:54:01] "POST /fruits HTTP/1.1" 201 - +2025-09-30 22:54:01,426 - INFO - REQUEST: PUT /fruits/1 - From 127.0.0.1 +2025-09-30 22:54:01,427 - INFO - RESPONSE: PUT /fruits/1 - Status 200 +2025-09-30 22:54:01,428 - INFO - 127.0.0.1 - - [30/Sep/2025 22:54:01] "PUT /fruits/1 HTTP/1.1" 200 - +2025-09-30 22:54:01,473 - INFO - REQUEST: DELETE /fruits/1 - From 127.0.0.1 +2025-09-30 22:54:01,474 - INFO - RESPONSE: DELETE /fruits/1 - Status 200 +2025-09-30 22:54:01,474 - INFO - 127.0.0.1 - - [30/Sep/2025 22:54:01] "DELETE /fruits/1 HTTP/1.1" 200 - +2025-09-30 22:54:01,516 - INFO - REQUEST: GET /fruits/search - From 127.0.0.1 +2025-09-30 22:54:01,516 - INFO - RESPONSE: GET /fruits/search - Status 200 +2025-09-30 22:54:01,516 - INFO - 127.0.0.1 - - [30/Sep/2025 22:54:01] "GET /fruits/search?name=apple HTTP/1.1" 200 - +2025-09-30 22:54:01,534 - INFO - REQUEST: GET /fruits/category/Tropical - From 127.0.0.1 +2025-09-30 22:54:01,535 - INFO - RESPONSE: GET /fruits/category/Tropical - Status 200 +2025-09-30 22:54:01,535 - INFO - 127.0.0.1 - - [30/Sep/2025 22:54:01] "GET /fruits/category/Tropical HTTP/1.1" 200 - +2025-09-30 22:55:23,112 - INFO - REQUEST: GET /docs - From 127.0.0.1 +2025-09-30 22:55:23,113 - INFO - RESPONSE: GET /docs - Status 404 +2025-09-30 22:55:23,114 - INFO - 127.0.0.1 - - [30/Sep/2025 22:55:23] "GET /docs HTTP/1.1" 404 - +2025-09-30 23:00:03,721 - INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on all addresses (0.0.0.0) + * Running on http://127.0.0.1:5000 + * Running on http://192.168.43.139:5000 +2025-09-30 23:00:03,722 - INFO - Press CTRL+C to quit +2025-09-30 23:00:03,734 - INFO - * Restarting with stat +2025-09-30 23:00:04,003 - WARNING - * Debugger is active! +2025-09-30 23:00:04,009 - INFO - * Debugger PIN: 117-497-176 +2025-09-30 23:00:06,690 - INFO - REQUEST: GET / - From 127.0.0.1 +2025-09-30 23:00:06,692 - INFO - RESPONSE: GET / - Status 200 +2025-09-30 23:00:06,693 - INFO - 127.0.0.1 - - [30/Sep/2025 23:00:06] "GET / HTTP/1.1" 200 - +2025-09-30 23:00:11,991 - INFO - REQUEST: GET /apidoce - From 127.0.0.1 +2025-09-30 23:00:11,992 - INFO - RESPONSE: GET /apidoce - Status 404 +2025-09-30 23:00:11,995 - INFO - 127.0.0.1 - - [30/Sep/2025 23:00:11] "GET /apidoce HTTP/1.1" 404 - +2025-09-30 23:00:18,194 - INFO - REQUEST: GET /apidocs - From 127.0.0.1 +2025-09-30 23:00:18,196 - INFO - RESPONSE: GET /apidocs - Status 308 +2025-09-30 23:00:18,197 - INFO - 127.0.0.1 - - [30/Sep/2025 23:00:18] "GET /apidocs HTTP/1.1" 308 - +2025-09-30 23:00:18,211 - INFO - REQUEST: GET /apidocs/ - From 127.0.0.1 +2025-09-30 23:00:18,302 - INFO - RESPONSE: GET /apidocs/ - Status 200 +2025-09-30 23:00:18,304 - INFO - 127.0.0.1 - - [30/Sep/2025 23:00:18] "GET /apidocs/ HTTP/1.1" 200 - +2025-09-30 23:00:18,371 - INFO - REQUEST: GET /flasgger_static/swagger-ui.css - From 127.0.0.1 +2025-09-30 23:00:18,372 - INFO - REQUEST: GET /flasgger_static/swagger-ui-bundle.js - From 127.0.0.1 +2025-09-30 23:00:18,374 - INFO - REQUEST: GET /flasgger_static/swagger-ui-standalone-preset.js - From 127.0.0.1 +2025-09-30 23:00:18,375 - INFO - REQUEST: GET /flasgger_static/lib/jquery.min.js - From 127.0.0.1 +2025-09-30 23:00:18,423 - INFO - RESPONSE: GET /flasgger_static/swagger-ui.css - Status 200 +2025-09-30 23:00:18,438 - INFO - 127.0.0.1 - - [30/Sep/2025 23:00:18] "GET /flasgger_static/swagger-ui.css HTTP/1.1" 200 - +2025-09-30 23:00:18,441 - INFO - RESPONSE: GET /flasgger_static/lib/jquery.min.js - Status 200 +2025-09-30 23:00:18,442 - INFO - 127.0.0.1 - - [30/Sep/2025 23:00:18] "GET /flasgger_static/lib/jquery.min.js HTTP/1.1" 200 - +2025-09-30 23:00:18,443 - INFO - RESPONSE: GET /flasgger_static/swagger-ui-standalone-preset.js - Status 200 +2025-09-30 23:00:18,445 - INFO - RESPONSE: GET /flasgger_static/swagger-ui-bundle.js - Status 200 +2025-09-30 23:00:18,449 - INFO - 127.0.0.1 - - [30/Sep/2025 23:00:18] "GET /flasgger_static/swagger-ui-standalone-preset.js HTTP/1.1" 200 - +2025-09-30 23:00:18,450 - INFO - 127.0.0.1 - - [30/Sep/2025 23:00:18] "GET /flasgger_static/swagger-ui-bundle.js HTTP/1.1" 200 - +2025-09-30 23:00:19,453 - INFO - REQUEST: GET /apispec_1.json - From 127.0.0.1 +2025-09-30 23:00:19,454 - INFO - RESPONSE: GET /apispec_1.json - Status 200 +2025-09-30 23:00:19,454 - INFO - 127.0.0.1 - - [30/Sep/2025 23:00:19] "GET /apispec_1.json HTTP/1.1" 200 - +2025-09-30 23:00:19,562 - INFO - REQUEST: GET /flasgger_static/favicon-32x32.png - From 127.0.0.1 +2025-09-30 23:00:19,564 - INFO - RESPONSE: GET /flasgger_static/favicon-32x32.png - Status 200 +2025-09-30 23:00:19,565 - INFO - 127.0.0.1 - - [30/Sep/2025 23:00:19] "GET /flasgger_static/favicon-32x32.png HTTP/1.1" 200 - +2025-09-30 23:02:02,020 - INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on all addresses (0.0.0.0) + * Running on http://127.0.0.1:5000 + * Running on http://192.168.43.139:5000 +2025-09-30 23:02:02,020 - INFO - Press CTRL+C to quit +2025-09-30 23:02:02,023 - INFO - * Restarting with stat +2025-09-30 23:02:02,281 - WARNING - * Debugger is active! +2025-09-30 23:02:02,292 - INFO - * Debugger PIN: 117-497-176 +2025-09-30 23:02:10,832 - INFO - REQUEST: GET /apidocs/ - From 127.0.0.1 +2025-09-30 23:02:10,908 - INFO - RESPONSE: GET /apidocs/ - Status 200 +2025-09-30 23:02:10,910 - INFO - 127.0.0.1 - - [30/Sep/2025 23:02:10] "GET /apidocs/ HTTP/1.1" 200 - +2025-09-30 23:02:10,966 - INFO - REQUEST: GET /flasgger_static/swagger-ui.css - From 127.0.0.1 +2025-09-30 23:02:10,982 - INFO - REQUEST: GET /flasgger_static/swagger-ui-bundle.js - From 127.0.0.1 +2025-09-30 23:02:10,984 - INFO - REQUEST: GET /flasgger_static/swagger-ui-standalone-preset.js - From 127.0.0.1 +2025-09-30 23:02:10,986 - INFO - RESPONSE: GET /flasgger_static/swagger-ui.css - Status 304 +2025-09-30 23:02:10,988 - INFO - REQUEST: GET /flasgger_static/lib/jquery.min.js - From 127.0.0.1 +2025-09-30 23:02:10,989 - INFO - 127.0.0.1 - - [30/Sep/2025 23:02:10] "GET /flasgger_static/swagger-ui.css HTTP/1.1" 304 - +2025-09-30 23:02:10,989 - INFO - RESPONSE: GET /flasgger_static/swagger-ui-bundle.js - Status 304 +2025-09-30 23:02:10,991 - INFO - RESPONSE: GET /flasgger_static/swagger-ui-standalone-preset.js - Status 304 +2025-09-30 23:02:10,993 - INFO - 127.0.0.1 - - [30/Sep/2025 23:02:10] "GET /flasgger_static/swagger-ui-bundle.js HTTP/1.1" 304 - +2025-09-30 23:02:10,994 - INFO - 127.0.0.1 - - [30/Sep/2025 23:02:10] "GET /flasgger_static/swagger-ui-standalone-preset.js HTTP/1.1" 304 - +2025-09-30 23:02:10,996 - INFO - RESPONSE: GET /flasgger_static/lib/jquery.min.js - Status 304 +2025-09-30 23:02:10,999 - INFO - 127.0.0.1 - - [30/Sep/2025 23:02:10] "GET /flasgger_static/lib/jquery.min.js HTTP/1.1" 304 - +2025-09-30 23:02:11,426 - INFO - REQUEST: GET /apispec_1.json - From 127.0.0.1 +2025-09-30 23:02:11,427 - INFO - RESPONSE: GET /apispec_1.json - Status 200 +2025-09-30 23:02:11,428 - INFO - 127.0.0.1 - - [30/Sep/2025 23:02:11] "GET /apispec_1.json HTTP/1.1" 200 - +2025-09-30 23:02:11,446 - INFO - REQUEST: GET /flasgger_static/favicon-32x32.png - From 127.0.0.1 +2025-09-30 23:02:11,447 - INFO - RESPONSE: GET /flasgger_static/favicon-32x32.png - Status 304 +2025-09-30 23:02:11,447 - INFO - 127.0.0.1 - - [30/Sep/2025 23:02:11] "GET /flasgger_static/favicon-32x32.png HTTP/1.1" 304 - +2025-09-30 23:03:14,463 - INFO - REQUEST: GET /apidocs/ - From 127.0.0.1 +2025-09-30 23:03:14,466 - INFO - RESPONSE: GET /apidocs/ - Status 200 +2025-09-30 23:03:14,468 - INFO - 127.0.0.1 - - [30/Sep/2025 23:03:14] "GET /apidocs/ HTTP/1.1" 200 - +2025-09-30 23:03:18,260 - INFO - REQUEST: GET /apispec_1.json - From 127.0.0.1 +2025-09-30 23:03:18,262 - INFO - RESPONSE: GET /apispec_1.json - Status 200 +2025-09-30 23:03:18,263 - INFO - 127.0.0.1 - - [30/Sep/2025 23:03:18] "GET /apispec_1.json HTTP/1.1" 200 - +2025-09-30 23:03:20,049 - INFO - REQUEST: GET /apispec_1.json - From 127.0.0.1 +2025-09-30 23:03:20,050 - INFO - RESPONSE: GET /apispec_1.json - Status 200 +2025-09-30 23:03:20,050 - INFO - 127.0.0.1 - - [30/Sep/2025 23:03:20] "GET /apispec_1.json HTTP/1.1" 200 - +2025-09-30 23:08:22,398 - INFO - REQUEST: GET /docs - From 127.0.0.1 +2025-09-30 23:08:22,399 - INFO - RESPONSE: GET /docs - Status 404 +2025-09-30 23:08:22,399 - INFO - 127.0.0.1 - - [30/Sep/2025 23:08:22] "GET /docs HTTP/1.1" 404 - diff --git a/fruit_api.py b/fruit_api.py index 5cab374..06f3642 100644 --- a/fruit_api.py +++ b/fruit_api.py @@ -1,91 +1,217 @@ -# fruit_api.py -from flask import Flask, jsonify, request +from flask import Flask, request, jsonify +from flasgger import Swagger from datetime import datetime -import logging app = Flask(__name__) -# ----------------------- -# Logging Configuration -# ----------------------- -LOG_FILE = "fruit_api.log" +# Swagger configuration (serve UI at /docs) +app.config["SWAGGER"] = { + "title": "Ahmed Gamal's Fruit API", + "uiversion": 3, + "swagger_ui": True, + "specs_route": "/docs/" # force Swagger UI to mount at /docs +} +swagger = Swagger(app) -logging.basicConfig( - filename=LOG_FILE, - level=logging.INFO, - format="%(asctime)s [%(levelname)s] %(message)s", -) +# Root endpoint (http://localhost:5000/) +@app.route("/", methods=["GET"]) +def home(): + return jsonify({ + "message": "Welcome to Ahmed Gamal's Fruit API 🚀", + "docs_url": "/docs" + }) -# In-memory database +# Sample data fruits = [ - {"id": 1, "name": "Apple", "color": "Red", "price": 1.50, "quantity": 100, "category": "Tropical"}, + {"id": 1, "name": "Apple", "color": "Red", "price": 1.5, "quantity": 100, "category": "Tropical"}, {"id": 2, "name": "Banana", "color": "Yellow", "price": 0.75, "quantity": 150, "category": "Tropical"}, - {"id": 3, "name": "Orange", "color": "Orange", "price": 1.20, "quantity": 80, "category": "Citrus"} + {"id": 3, "name": "Orange", "color": "Orange", "price": 1.2, "quantity": 80, "category": "Citrus"} ] -# ----------------------- -# Logging Hooks -# ----------------------- -@app.before_request -def log_request(): - logging.info( - f"REQUEST: method={request.method} path={request.path} " - f"args={dict(request.args)} body={request.get_json(silent=True)} " - f"ip={request.remote_addr}" - ) +@app.route("/health", methods=["GET"]) +def health(): + """ + Health Check + --- + tags: + - Health + responses: + 200: + description: API is healthy + """ + return jsonify({ + "service": "fruit-api", + "status": "healthy", + "timestamp": datetime.utcnow().isoformat() + }) -@app.after_request -def log_response(response): - logging.info( - f"RESPONSE: method={request.method} path={request.path} " - f"status={response.status_code} ip={request.remote_addr}" - ) - return response - -# ----------------------- -# API Endpoints -# ----------------------- -@app.route('/') -def home(): - return jsonify({"message": "Fruit Store API", "version": "1.0"}) - -@app.route('/fruits', methods=['GET']) -def get_all_fruits(): +@app.route("/fruits", methods=["GET"]) +def get_fruits(): + """ + Get All Fruits + --- + tags: + - Fruits + responses: + 200: + description: A list of all fruits + """ return jsonify({"fruits": fruits, "total": len(fruits)}) -@app.route('/fruits/', methods=['GET']) +@app.route("/fruits/", methods=["GET"]) def get_fruit(fruit_id): - fruit = next((f for f in fruits if f['id'] == fruit_id), None) + """ + Get a Fruit by ID + --- + tags: + - Fruits + parameters: + - name: fruit_id + in: path + type: integer + required: true + responses: + 200: + description: Fruit details + 404: + description: Fruit not found + """ + fruit = next((f for f in fruits if f["id"] == fruit_id), None) if fruit: return jsonify({"fruit": fruit}) return jsonify({"error": "Fruit not found"}), 404 -@app.route('/fruits', methods=['POST']) +@app.route("/fruits", methods=["POST"]) def create_fruit(): + """ + Create a New Fruit + --- + tags: + - Fruits + parameters: + - name: body + in: body + required: true + schema: + type: object + properties: + name: {type: string} + color: {type: string} + price: {type: number} + quantity: {type: integer} + category: {type: string} + responses: + 201: + description: Fruit created + """ data = request.get_json() - if not data or 'name' not in data: - return jsonify({"error": "Name is required"}), 400 - - new_id = max([f['id'] for f in fruits]) + 1 if fruits else 1 new_fruit = { - "id": new_id, - "name": data['name'], - "color": data.get('color', 'Unknown'), - "price": data.get('price', 0.0), - "quantity": data.get('quantity', 0), - "category": data.get('category', 'General'), - "created_at": datetime.now().isoformat() + "id": len(fruits) + 1, + "name": data.get("name"), + "color": data.get("color"), + "price": data.get("price"), + "quantity": data.get("quantity"), + "category": data.get("category"), + "created_at": datetime.utcnow().isoformat() } fruits.append(new_fruit) return jsonify({"message": "Fruit created successfully", "fruit": new_fruit}), 201 -@app.route('/health', methods=['GET']) -def health_check(): - return jsonify({"status": "healthy", "service": "fruit-api"}) +@app.route("/fruits/", methods=["PUT"]) +def update_fruit(fruit_id): + """ + Update a Fruit + --- + tags: + - Fruits + parameters: + - name: fruit_id + in: path + type: integer + required: true + - name: body + in: body + required: true + schema: + type: object + responses: + 200: + description: Fruit updated + 404: + description: Fruit not found + """ + fruit = next((f for f in fruits if f["id"] == fruit_id), None) + if not fruit: + return jsonify({"error": "Fruit not found"}), 404 -# ----------------------- -# Run API -# ----------------------- -if __name__ == '__main__': - print("Fruit API starting on http://localhost:5000") - app.run(debug=False, host='0.0.0.0', port=5000) + data = request.get_json() + fruit.update(data) + fruit["updated_at"] = datetime.utcnow().isoformat() + return jsonify({"message": "Fruit updated successfully", "fruit": fruit}) + +@app.route("/fruits/", methods=["DELETE"]) +def delete_fruit(fruit_id): + """ + Delete a Fruit + --- + tags: + - Fruits + parameters: + - name: fruit_id + in: path + type: integer + required: true + responses: + 200: + description: Fruit deleted + 404: + description: Fruit not found + """ + global fruits + fruit = next((f for f in fruits if f["id"] == fruit_id), None) + if not fruit: + return jsonify({"error": "Fruit not found"}), 404 + fruits = [f for f in fruits if f["id"] != fruit_id] + return jsonify({"message": "Fruit deleted successfully", "deleted_fruit": fruit}) + +@app.route("/fruits/search", methods=["GET"]) +def search_fruits(): + """ + Search Fruits by Name + --- + tags: + - Fruits + parameters: + - name: name + in: query + type: string + required: true + responses: + 200: + description: Search results + """ + name = request.args.get("name", "").lower() + results = [f for f in fruits if name in f["name"].lower()] + return jsonify({"search_term": name, "count": len(results), "results": results}) + +@app.route("/fruits/category/", methods=["GET"]) +def get_fruits_by_category(category): + """ + Get Fruits by Category + --- + tags: + - Fruits + parameters: + - name: category + in: path + type: string + required: true + responses: + 200: + description: Fruits by category + """ + results = [f for f in fruits if f["category"].lower() == category.lower()] + return jsonify({"category": category, "count": len(results), "fruits": results}) + +if __name__ == "__main__": + app.run(debug=True, host="0.0.0.0", port=5000) diff --git a/requirements.txt b/requirements.txt index 7b5701b..85a9021 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ # requirements.txt -Flask==2.3.3 \ No newline at end of file +Flask==2.3.3 +flasgger diff --git a/test_api.sh b/test_api.sh new file mode 100755 index 0000000..1c502ea --- /dev/null +++ b/test_api.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash + +# test_api.sh +# Script to test Fruit API endpoints and log responses + +API_URL="http://localhost:5000" +LOG_FILE="test_results.log" + +echo "🚀 Running API tests at $(date)" | tee -a "$LOG_FILE" +echo "======================================" | tee -a "$LOG_FILE" + +# 1. Health Check +echo "🔹 Testing /health" | tee -a "$LOG_FILE" +curl -s -w "\nStatus: %{http_code}\n" "$API_URL/health" | tee -a "$LOG_FILE" +echo "--------------------------------------" | tee -a "$LOG_FILE" + +# 2. Get all fruits +echo "🔹 Testing GET /fruits" | tee -a "$LOG_FILE" +curl -s -w "\nStatus: %{http_code}\n" "$API_URL/fruits" | tee -a "$LOG_FILE" +echo "--------------------------------------" | tee -a "$LOG_FILE" + +# 3. Get fruit by ID (1) +echo "🔹 Testing GET /fruits/1" | tee -a "$LOG_FILE" +curl -s -w "\nStatus: %{http_code}\n" "$API_URL/fruits/1" | tee -a "$LOG_FILE" +echo "--------------------------------------" | tee -a "$LOG_FILE" + +# 4. Create new fruit +echo "🔹 Testing POST /fruits" | tee -a "$LOG_FILE" +curl -s -X POST -H "Content-Type: application/json" \ + -d '{"name":"Mango","color":"Yellow","price":2.5,"quantity":50,"category":"Tropical"}' \ + -w "\nStatus: %{http_code}\n" "$API_URL/fruits" | tee -a "$LOG_FILE" +echo "--------------------------------------" | tee -a "$LOG_FILE" + +# 5. Update fruit ID 1 +echo "🔹 Testing PUT /fruits/1" | tee -a "$LOG_FILE" +curl -s -X PUT -H "Content-Type: application/json" \ + -d '{"name":"Green Apple","price":1.8}' \ + -w "\nStatus: %{http_code}\n" "$API_URL/fruits/1" | tee -a "$LOG_FILE" +echo "--------------------------------------" | tee -a "$LOG_FILE" + +# 6. Delete fruit ID 1 +echo "🔹 Testing DELETE /fruits/1" | tee -a "$LOG_FILE" +curl -s -X DELETE -w "\nStatus: %{http_code}\n" "$API_URL/fruits/1" | tee -a "$LOG_FILE" +echo "--------------------------------------" | tee -a "$LOG_FILE" + +# 7. Search fruits +echo "🔹 Testing GET /fruits/search?name=apple" | tee -a "$LOG_FILE" +curl -s -w "\nStatus: %{http_code}\n" "$API_URL/fruits/search?name=apple" | tee -a "$LOG_FILE" +echo "--------------------------------------" | tee -a "$LOG_FILE" + +# 8. Get fruits by category +echo "🔹 Testing GET /fruits/category/Tropical" | tee -a "$LOG_FILE" +curl -s -w "\nStatus: %{http_code}\n" "$API_URL/fruits/category/Tropical" | tee -a "$LOG_FILE" +echo "--------------------------------------" | tee -a "$LOG_FILE" + +echo "✅ Tests completed at $(date)" | tee -a "$LOG_FILE" +echo "======================================" | tee -a "$LOG_FILE" diff --git a/test_results.log b/test_results.log new file mode 100644 index 0000000..65f0882 --- /dev/null +++ b/test_results.log @@ -0,0 +1,505 @@ +🚀 Running API tests at Tue 30 Sep 2025 10:43:38 PM EEST +====================================== +🔹 Testing /health + +Status: 000 +-------------------------------------- +🔹 Testing GET /fruits + +Status: 000 +-------------------------------------- +🔹 Testing GET /fruits/1 + +Status: 000 +-------------------------------------- +🔹 Testing POST /fruits + +Status: 000 +-------------------------------------- +🔹 Testing PUT /fruits/1 + +Status: 000 +-------------------------------------- +🔹 Testing DELETE /fruits/1 + +Status: 000 +-------------------------------------- +🔹 Testing GET /fruits/search?name=apple + +Status: 000 +-------------------------------------- +🔹 Testing GET /fruits/category/Tropical + +Status: 000 +-------------------------------------- +✅ Tests completed at Tue 30 Sep 2025 10:43:39 PM EEST +====================================== +🚀 Running API tests at Tue 30 Sep 2025 10:47:56 PM EEST +====================================== +🔹 Testing /health +{"service":"fruit-api","status":"healthy"} + +Status: 200 +-------------------------------------- +🔹 Testing GET /fruits +{"fruits":[{"category":"Tropical","color":"Red","id":1,"name":"Apple","price":1.5,"quantity":100},{"category":"Tropical","color":"Yellow","id":2,"name":"Banana","price":0.75,"quantity":150},{"category":"Citrus","color":"Orange","id":3,"name":"Orange","price":1.2,"quantity":80}],"total":3} + +Status: 200 +-------------------------------------- +🔹 Testing GET /fruits/1 +{"fruit":{"category":"Tropical","color":"Red","id":1,"name":"Apple","price":1.5,"quantity":100}} + +Status: 200 +-------------------------------------- +🔹 Testing POST /fruits +{"fruit":{"category":"Tropical","color":"Yellow","created_at":"2025-09-30T22:47:56.301904","id":4,"name":"Mango","price":2.5,"quantity":50},"message":"Fruit created successfully"} + +Status: 201 +-------------------------------------- +🔹 Testing PUT /fruits/1 + + +405 Method Not Allowed +

Method Not Allowed

+

The method is not allowed for the requested URL.

+ +Status: 405 +-------------------------------------- +🔹 Testing DELETE /fruits/1 + + +405 Method Not Allowed +

Method Not Allowed

+

The method is not allowed for the requested URL.

+ +Status: 405 +-------------------------------------- +🔹 Testing GET /fruits/search?name=apple + + +404 Not Found +

Not Found

+

The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.

+ +Status: 404 +-------------------------------------- +🔹 Testing GET /fruits/category/Tropical + + +404 Not Found +

Not Found

+

The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.

+ +Status: 404 +-------------------------------------- +✅ Tests completed at Tue 30 Sep 2025 10:47:56 PM EEST +====================================== +🚀 Running API tests at Tue 30 Sep 2025 10:48:14 PM EEST +====================================== +🔹 Testing /health +{"service":"fruit-api","status":"healthy"} + +Status: 200 +-------------------------------------- +🔹 Testing GET /fruits +{"fruits":[{"category":"Tropical","color":"Red","id":1,"name":"Apple","price":1.5,"quantity":100},{"category":"Tropical","color":"Yellow","id":2,"name":"Banana","price":0.75,"quantity":150},{"category":"Citrus","color":"Orange","id":3,"name":"Orange","price":1.2,"quantity":80},{"category":"Tropical","color":"Yellow","created_at":"2025-09-30T22:47:56.301904","id":4,"name":"Mango","price":2.5,"quantity":50}],"total":4} + +Status: 200 +-------------------------------------- +🔹 Testing GET /fruits/1 +{"fruit":{"category":"Tropical","color":"Red","id":1,"name":"Apple","price":1.5,"quantity":100}} + +Status: 200 +-------------------------------------- +🔹 Testing POST /fruits +{"fruit":{"category":"Tropical","color":"Yellow","created_at":"2025-09-30T22:48:14.534108","id":5,"name":"Mango","price":2.5,"quantity":50},"message":"Fruit created successfully"} + +Status: 201 +-------------------------------------- +🔹 Testing PUT /fruits/1 + + +405 Method Not Allowed +

Method Not Allowed

+

The method is not allowed for the requested URL.

+ +Status: 405 +-------------------------------------- +🔹 Testing DELETE /fruits/1 + + +405 Method Not Allowed +

Method Not Allowed

+

The method is not allowed for the requested URL.

+ +Status: 405 +-------------------------------------- +🔹 Testing GET /fruits/search?name=apple + + +404 Not Found +

Not Found

+

The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.

+ +Status: 404 +-------------------------------------- +🔹 Testing GET /fruits/category/Tropical + + +404 Not Found +

Not Found

+

The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.

+ +Status: 404 +-------------------------------------- +✅ Tests completed at Tue 30 Sep 2025 10:48:14 PM EEST +====================================== +🚀 Running API tests at Tue 30 Sep 2025 10:48:28 PM EEST +====================================== +🔹 Testing /health +{"service":"fruit-api","status":"healthy"} + +Status: 200 +-------------------------------------- +🔹 Testing GET /fruits +{"fruits":[{"category":"Tropical","color":"Red","id":1,"name":"Apple","price":1.5,"quantity":100},{"category":"Tropical","color":"Yellow","id":2,"name":"Banana","price":0.75,"quantity":150},{"category":"Citrus","color":"Orange","id":3,"name":"Orange","price":1.2,"quantity":80},{"category":"Tropical","color":"Yellow","created_at":"2025-09-30T22:47:56.301904","id":4,"name":"Mango","price":2.5,"quantity":50},{"category":"Tropical","color":"Yellow","created_at":"2025-09-30T22:48:14.534108","id":5,"name":"Mango","price":2.5,"quantity":50}],"total":5} + +Status: 200 +-------------------------------------- +🔹 Testing GET /fruits/1 +{"fruit":{"category":"Tropical","color":"Red","id":1,"name":"Apple","price":1.5,"quantity":100}} + +Status: 200 +-------------------------------------- +🔹 Testing POST /fruits +{"fruit":{"category":"Tropical","color":"Yellow","created_at":"2025-09-30T22:48:28.894050","id":6,"name":"Mango","price":2.5,"quantity":50},"message":"Fruit created successfully"} + +Status: 201 +-------------------------------------- +🔹 Testing PUT /fruits/1 + + +405 Method Not Allowed +

Method Not Allowed

+

The method is not allowed for the requested URL.

+ +Status: 405 +-------------------------------------- +🔹 Testing DELETE /fruits/1 + + +405 Method Not Allowed +

Method Not Allowed

+

The method is not allowed for the requested URL.

+ +Status: 405 +-------------------------------------- +🔹 Testing GET /fruits/search?name=apple + + +404 Not Found +

Not Found

+

The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.

+ +Status: 404 +-------------------------------------- +🔹 Testing GET /fruits/category/Tropical + + +404 Not Found +

Not Found

+

The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.

+ +Status: 404 +-------------------------------------- +✅ Tests completed at Tue 30 Sep 2025 10:48:28 PM EEST +====================================== +🚀 Running API tests at Tue 30 Sep 2025 10:54:01 PM EEST +====================================== +🔹 Testing /health +{ + "service": "fruit-api", + "status": "healthy", + "timestamp": "2025-09-30T22:54:01.228357" +} + +Status: 200 +-------------------------------------- +🔹 Testing GET /fruits +{ + "fruits": [ + { + "category": "Tropical", + "color": "Red", + "id": 1, + "name": "Apple", + "price": 1.5, + "quantity": 100 + }, + { + "category": "Tropical", + "color": "Yellow", + "id": 2, + "name": "Banana", + "price": 0.75, + "quantity": 150 + }, + { + "category": "Citrus", + "color": "Orange", + "id": 3, + "name": "Orange", + "price": 1.2, + "quantity": 80 + } + ], + "timestamp": "2025-09-30T22:54:01.275312", + "total": 3 +} + +Status: 200 +-------------------------------------- +🔹 Testing GET /fruits/1 +{ + "fruit": { + "category": "Tropical", + "color": "Red", + "id": 1, + "name": "Apple", + "price": 1.5, + "quantity": 100 + } +} + +Status: 200 +-------------------------------------- +🔹 Testing POST /fruits +{ + "fruit": { + "category": "Tropical", + "color": "Yellow", + "created_at": "2025-09-30T22:54:01.376254", + "id": 4, + "name": "Mango", + "price": 2.5, + "quantity": 50 + }, + "message": "Fruit created successfully" +} + +Status: 201 +-------------------------------------- +🔹 Testing PUT /fruits/1 +{ + "fruit": { + "category": "Tropical", + "color": "Red", + "id": 1, + "name": "Green Apple", + "price": 1.8, + "quantity": 100, + "updated_at": "2025-09-30T22:54:01.427456" + }, + "message": "Fruit updated successfully" +} + +Status: 200 +-------------------------------------- +🔹 Testing DELETE /fruits/1 +{ + "deleted_fruit": { + "category": "Tropical", + "color": "Red", + "id": 1, + "name": "Green Apple", + "price": 1.8, + "quantity": 100, + "updated_at": "2025-09-30T22:54:01.427456" + }, + "message": "Fruit deleted successfully" +} + +Status: 200 +-------------------------------------- +🔹 Testing GET /fruits/search?name=apple +{ + "count": 0, + "results": [], + "search_term": "apple" +} + +Status: 200 +-------------------------------------- +🔹 Testing GET /fruits/category/Tropical +{ + "category": "Tropical", + "count": 2, + "fruits": [ + { + "category": "Tropical", + "color": "Yellow", + "id": 2, + "name": "Banana", + "price": 0.75, + "quantity": 150 + }, + { + "category": "Tropical", + "color": "Yellow", + "created_at": "2025-09-30T22:54:01.376254", + "id": 4, + "name": "Mango", + "price": 2.5, + "quantity": 50 + } + ] +} + +Status: 200 +-------------------------------------- +✅ Tests completed at Tue 30 Sep 2025 10:54:01 PM EEST +====================================== +🚀 Running API tests at Tue 30 Sep 2025 11:14:57 PM EEST +====================================== +🔹 Testing /health +{ + "service": "fruit-api", + "status": "healthy", + "timestamp": "2025-09-30T20:14:57.077152" +} + +Status: 200 +-------------------------------------- +🔹 Testing GET /fruits +{ + "fruits": [ + { + "category": "Tropical", + "color": "Red", + "id": 1, + "name": "Apple", + "price": 1.5, + "quantity": 100 + }, + { + "category": "Tropical", + "color": "Yellow", + "id": 2, + "name": "Banana", + "price": 0.75, + "quantity": 150 + }, + { + "category": "Citrus", + "color": "Orange", + "id": 3, + "name": "Orange", + "price": 1.2, + "quantity": 80 + } + ], + "total": 3 +} + +Status: 200 +-------------------------------------- +🔹 Testing GET /fruits/1 +{ + "fruit": { + "category": "Tropical", + "color": "Red", + "id": 1, + "name": "Apple", + "price": 1.5, + "quantity": 100 + } +} + +Status: 200 +-------------------------------------- +🔹 Testing POST /fruits +{ + "fruit": { + "category": "Tropical", + "color": "Yellow", + "created_at": "2025-09-30T20:14:57.129021", + "id": 4, + "name": "Mango", + "price": 2.5, + "quantity": 50 + }, + "message": "Fruit created successfully" +} + +Status: 201 +-------------------------------------- +🔹 Testing PUT /fruits/1 +{ + "fruit": { + "category": "Tropical", + "color": "Red", + "id": 1, + "name": "Green Apple", + "price": 1.8, + "quantity": 100, + "updated_at": "2025-09-30T20:14:57.150810" + }, + "message": "Fruit updated successfully" +} + +Status: 200 +-------------------------------------- +🔹 Testing DELETE /fruits/1 +{ + "deleted_fruit": { + "category": "Tropical", + "color": "Red", + "id": 1, + "name": "Green Apple", + "price": 1.8, + "quantity": 100, + "updated_at": "2025-09-30T20:14:57.150810" + }, + "message": "Fruit deleted successfully" +} + +Status: 200 +-------------------------------------- +🔹 Testing GET /fruits/search?name=apple +{ + "count": 0, + "results": [], + "search_term": "apple" +} + +Status: 200 +-------------------------------------- +🔹 Testing GET /fruits/category/Tropical +{ + "category": "Tropical", + "count": 2, + "fruits": [ + { + "category": "Tropical", + "color": "Yellow", + "id": 2, + "name": "Banana", + "price": 0.75, + "quantity": 150 + }, + { + "category": "Tropical", + "color": "Yellow", + "created_at": "2025-09-30T20:14:57.129021", + "id": 4, + "name": "Mango", + "price": 2.5, + "quantity": 50 + } + ] +} + +Status: 200 +-------------------------------------- +✅ Tests completed at Tue 30 Sep 2025 11:14:57 PM EEST +======================================