Create API with flask

 

 

Server-Side: Flask API Development

 

We will build a simple API that will tell the current time. And then add more feature.

The explanation and the code

 

 

The code


 
 from flask import Flask, request, jsonify
 from datetime import datetime
 
 app = Flask(__name__) 
 
 # Define a route to get the current time
 @app.route('/get-current-time', methods=['POST'])
 def get_current_time():
     # Validate the API key
     api_key = request.headers.get('Authorization')
     if api_key != '12345': 
         return jsonify({"error": "Unauthorized"}), 401 
 
     # Get and format the current time
     current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
 
     # Return the time in JSON format
     return jsonify({"currentTime": current_time}), 200 
 
 if __name__ == '__main__':
     app.run(port=5000, debug=True) 
 
 
 
  

 

 

 

 

 

Route Definition: Use the @app.route() decorator to define the URL path (/get-current-time) for your API endpoint. This specific endpoint is configured to handle POST requests.
Endpoint Logic: Inside the get_current_time() function (which handles requests to your endpoint), retrieve the API key from the incoming request's headers
Authorization Check: Implement a security measure by verifying that the provided API key matches the correct value. If the key is invalid, return a JSON error response with a 401 (Unauthorized) HTTP status code.
 
 

Response Preparation: Construct a JSON dictionary (response_data) to hold the current time value.

 

 

Client-Side: Calling the API

 


 
 
 import requests
 
 url = 'http://localhost:5000/get-current-time'
 api_key = '12345'
 
 headers = {
   'Authorization': api_key,
   'Content-Type': 'application/json',
 }
 
 try:
   response = requests.post(url, headers=headers)
 
   if response.status_code == 200:
     response_data = response.json()
     current_time = response_data.get('currentTime')
     print("Current time received from the API:", current_time)
   else:
     print("Error:", response.status_code, response.text)  # Include response text
 except requests.exceptions.RequestException as e:
   print("Error On request:", e)
 
 
 
  

 

In the client side we will use requests module to retrieve the time with the API request.

requests module is not a built-in module in Python. So if you have not installed you need to install it first.

pip install requests

 

 

The code and the explanations

 

 

url = 'http://localhost:5000/get-current-time'
 api_key = 'oCZ2DNROIRSyL058'
 
 headers = {
   'Authorization': api_key,
   'Content-Type': 'application/json',
 }

Set API URL and Key: Configure the address of your API endpoint and your valid API key.
Create Headers: Build a dictionary containing your API key for authorization and the content type (application/json).

 


 

 

 

Testing the code

 

 

  • First we need to run the code we have add in the top for server side. It will run a server on local host http://localhost:5000/
  • Then we need to run another python script that is written for the client side. That's all! It will print the time which comes from the server.

This was just for essential approach. We can make it more practical. For example we need check if a number is prime or not but we do not want to write the core functionality in our client side code. So we can write the API for it .. And call when ever we need and wherever we are!

We will use Miller-Rabin Primality Test for more efficiency to check a number is prime or not.

 

The code that checks the number is prime or not

 

 


 
 
 import random
 
 def is_prime_miller_rabin(n, iterations=40):
     """Performs the Miller-Rabin Primality Test to determine if a number is likely prime.
 
     This test is probabilistic, meaning it's highly accurate but not foolproof.
     Increasing the 'iterations' value improves the accuracy of the result.
 
     Args:
         n: The integer to test for primality.
         iterations: Number of test rounds to perform (default is 40).
 
     Returns:
         True if the number is likely prime, False if it's not.
     """
 
     if n <= 1:
         return False
     if n <= 3:
         return True
     if n % 2 == 0:
         return False
 
     # Decompose n-1 into the form 2^r * d
     d = n - 1
     r = 0
     while d % 2 == 0:
         d //= 2
         r += 1
 
     # Witness loop
     for _ in range(iterations):
         a = random.randint(2, n - 2)
         x = pow(a, d, n)
         if x == 1 or x == n - 1:
             continue
         for _ in range(r - 1):
             x = pow(x, 2, n)
             if x == n - 1:
                 break
         else:
             return False
     return True
 
 
 
 # Test the code
 number_to_test = int(input("Enter a number to check for primality: "))
 if is_prime_miller_rabin(number_to_test):
     print(f"{number_to_test} is likely a prime number.")
 else:
     print(f"{number_to_test} is not a prime number.") 
 
 
 
  

If you are interested in prime numbers you also can read this article

 

 

Implemented In The server code( API)

 


 
 
 from flask import Flask, request, jsonify
 from datetime import datetime
 import random
 
 app = Flask(__name__) 
 
 def is_prime_miller_rabin(n, iterations=40):
     """Performs the Miller-Rabin Primality Test to determine if a number is likely prime."""
     if n <= 1:
         return False
     if n <= 3:
         return True
     if n % 2 == 0:
         return False
 
     # Decompose n-1 into the form 2^r * d
     d = n - 1
     r = 0
     while d % 2 == 0:
         d //= 2
         r += 1
 
     # Witness loop
     for _ in range(iterations):
         a = random.randint(2, n - 2)
         x = pow(a, d, n)
         if x == 1 or x == n - 1:
             continue
         for _ in range(r - 1):
             x = pow(x, 2, n)
             if x == n - 1:
                 break
         else:
             return False
     return True
 
 # Define a route to check if a number is prime
 @app.route('/check-prime', methods=['POST'])
 def check_prime():
     # Validate the API key
     api_key = request.headers.get('Authorization')
     if api_key != '12345': 
         return jsonify({"error": "Unauthorized"}), 401 
 
     # Get the number from the request
     data = request.get_json()
     number_to_test = data.get('number')
 
     # Check if the number is prime
     is_prime = is_prime_miller_rabin(number_to_test)
 
     # Return the result
     return jsonify({"number": number_to_test, "isPrime": is_prime}), 200 
 
 if __name__ == '__main__':
     app.run(port=5000, debug=True) 
 
 
 
 
  

 

Calling from the client side


 
 
 import requests
 
 url = 'http://127.0.0.1:5000/check-prime'
 headers = {'Authorization': '12345'}
 data = {'number': 172983479832623897492387592384682937659382477}
 
 response = requests.post(url, json=data, headers=headers)
 print(response.json())
 
 
 
 
  

 

 

Limit the API calling: Setting the Rate-Limiting

 

We can specifically set the daily limit or hourly limit for specific user to save the computation limits. For this we will use a wonderful library apscheduler . I first used this library on video calling project for user data management scheduler.

Install the library with

pip install apscheduler

 

Now our code will look like this


 
 
 from flask import Flask, request, jsonify
 from datetime import datetime, timedelta
 import random
 from apscheduler.schedulers.background import BackgroundScheduler
 
 app = Flask(__name__)
 
 def is_prime_miller_rabin(n, iterations=40):
     """Performs the Miller-Rabin Primality Test to determine if a number is likely prime."""
     if n <= 1:
         return False
     if n <= 3:
         return True
     if n % 2 == 0:
         return False
 
     # Decompose n-1 into the form 2^r * d
     d = n - 1
     r = 0
     while d % 2 == 0:
         d //= 2
         r += 1
 
     # Witness loop
     for _ in range(iterations):
         a = random.randint(2, n - 2)
         x = pow(a, d, n)
         if x == 1 or x == n - 1:
             continue
         for _ in range(r - 1):
             x = pow(x, 2, n)
             if x == n - 1:
                 break
         else:
             return False
     return True
 
 # Initialize the scheduler
 scheduler = BackgroundScheduler()
 
 # Define the users and their limits
 users = {"12345": {"limit": 5}, "45365": {"limit": 5}}
 
 # Function to reset the limits
 def reset_limits():
     print("Resetting limits...")
     for user_info in users.values():
         user_info["limit"] = 5
 
 # Schedule the job to run every 24 hours
 scheduler.add_job(reset_limits, 'interval', hours=24)
 
 # Start the scheduler
 scheduler.start()
 
 # Define a route to check if a number is prime
 @app.route('/check-prime', methods=['POST'])
 def check_prime():
     # Validate the API key
     api_key = request.headers.get('Authorization')
     if api_key not in users:
         return jsonify({"error": "Unauthorized"}), 401
 
     # Get the number from the request
     limit = users[api_key]['limit']
     if not limit == 0:
         data = request.get_json()
         number_to_test = data.get('number')
 
         # Check if the number is prime
         is_prime = is_prime_miller_rabin(number_to_test)
 
         # Update the request limit
         users[api_key]['limit'] -= 1
 
         # Return the result
         return jsonify({"number": number_to_test, "isPrime": is_prime}), 200
     else:
         return jsonify({"error": "Request limit exceeded. Please try again later."}), 429
 
 if __name__ == '__main__':
     app.run(port=5000, debug=True)
 
 
 
 
  

 

 

Client Side will be unchanged!


 
 
 import requests
 
 url = 'http://127.0.0.1:5000/check-prime'
 headers = {'Authorization': '12345'}
 data = {'number': 172983479832623897492387592384682937659382477}
 
 response = requests.post(url, json=data, headers=headers)
 print(response.json())
 
 
 
  

 

 

 

Enhance Security Level

For demonstration purposes, this example stores the API key directly in the code. In production environments, always store API keys securely in a database with hashing to protect sensitive information.

With timestamp make the API key ultimately unique when generate new key for user


 
 
 import secrets
 import string
 import time
 
 def generate_unique_api_key(length=32):
     """Generate a unique API key using a combination of random characters and timestamp."""
     timestamp = str(int(time.time()))  # Get current timestamp as a string
     alphabet = string.ascii_letters + string.digits
     random_part = ''.join(secrets.choice(alphabet) for _ in range(length - len(timestamp)))
     key = timestamp + random_part
     return key
 
 # Generate a unique API key of length 32
 api_key = generate_unique_api_key()
 print("unique API key:", api_key)
 
 
 
 
  

 

 

 

For You

For more easy to use, I added the code in the github repository

 

 

Tags