API call

Requests is an elegant and simple HTTP library for Python, built for human beings.

  • Installing Requests:
To get started with requests, you need to install the library. This can be done via pip:
python -m pip install requests

  • Importing Requests:
Once installed, you can import the requests module in your Python code:
import requests

  • Making a GET Request:
A common use of requests is to fetch data from a URL (e.g., a webpage or an API). For example, let’s get GitHub’s public timeline:
r = requests.get('https://api.github.com/events')
This line makes an HTTP GET request to the specified URL and stores the server’s response in the r object.

  • Accessing Response Data:
After making the request, the r object is a Response object that contains information about the request, including:

  • Status Code: Indicates whether the request was successful (e.g., r.status_code).
  • Response Content: The data returned by the server, usually in JSON or HTML format (e.g., r.text for plain text or r.json() for JSON).
  • Headers: Additional information about the response, such as the content type (e.g., r.headers).
  • Example Usage:
# Status code of the response
  • print(r.status_code)
# The raw HTML or text content of the page
  • print(r.text)
# If the response is in JSON format, you can use the .json() method to parse it
  • data = r.json()
  • print(data)
Key Takeaways:
  • requests.get(): Used to make a GET request to a URL.
  • Response Object (r): Contains details about the request and the server's response.
  • Attributes: You can access status_code, text, and json() to get information about the response.

Passing Parameters In URLs

Passing parameters: The act of adding key=value pairs to the URL to customize the request.

  • Constructing the URL:

    • Normally, if you were building the URL manually, you would add query parameters directly after the ? in the URL, like this:
      https://httpbin.org/get?key1=value1&key2=value2
  • Using requests.get() with the params keyword:

    • Instead of manually constructing the URL, you can pass the query parameters as a dictionary to the params argument of the requests.get() function.
    • Example:
      payload = {'key1': 'value1', 'key2': 'value2'}
      r = requests.get('https://httpbin.org/get', params=payload)
  • How requests Handles URL Encoding:

    • The requests library automatically encodes the dictionary into query parameters and appends them to the URL, even if you don't manually format the string.
  • Checking the Final URL:

    • You can print the final URL with the parameters encoded:
      print(r.url)
      Output:
      https://httpbin.org/get?key2=value2&key1=value1


How you can explain an API client-server setup using Python in an interview

in short: In a client-server architecture, I use Python as the client to send API requests to a server using libraries like requests. The server processes the requests, executes necessary operations, and returns responses, typically in JSON format. For authentication, I implement token-based methods like API keys or OAuth. I also handle error responses (e.g., HTTP 401 or 429) to ensure the client communicates securely and efficiently with the server.

In detail: In an API client-server architecture, the client is the application that sends requests to the server, and the server is the system that processes these requests and responds with the required data or actions. In my experience, I have used Python as the client to interact with APIs by leveraging libraries like requests. For example, I sent GET and POST requests to endpoints like https://api.example.com/data to fetch or submit data.

The server, which hosts the API, processes these requests by performing actions such as querying a database or executing business logic. It then responds with data, often in JSON format, which I parse and transform using Python libraries like json or pandas.

I have also implemented secure client-server communication using token-based authentication mechanisms like API keys or OAuth. Additionally, I handled error responses from the server, such as rate-limiting (HTTP 429) or unauthorized access (HTTP 401), ensuring the client application is robust and resilient...

how we  handled 429 errors? In simple terms, this code tries to get weather data. If the server says "too many requests" (429), the code waits for a bit (longer each time it happens) and then tries again, up to a maximum of 3 times.

how we handled 401 error? 

  • Recognizing the Error: Check for the HTTP status code 401.
  • Prompting for Credentials: If the user hasn't provided credentials yet, prompt them to enter their username and password or other required authentication information (e.g., API key).
  • Refreshing Tokens (if using OAuth 2.0): If you're using an authentication protocol like OAuth 2.0, a 401 often means the access token has expired. Your application should attempt to refresh the access token using a refresh token (if you have one).
  • Verbs: verbs describe actions, and in this case, it describes what action to take on the data/resource.

    Example of HTTP Verbs (Methods):

    • GET: Retrieve data (action = "get")
    • POST: Send or create data (action = "post")
    • PUT: Update existing data (action = "put")
    • DELETE: Remove data (action = "delete")

    These verbs (GET, POST, PUT, DELETE, etc.) are used to define the action that the server should perform when a request is made. Each verb is tied to a specific operation, which helps define the behavior of the HTTP request.

    HTTP status code verbs: In HTTP, status codes are three-digit numbers returned by the server to indicate the result of an HTTP request

    Summary of HTTP Status Code Categories:

    Status Code ClassVerb/ActionExample Codes
    1xxInformational100, 101, 102
    2xxSuccess/Completion200 (OK), 201 (Created)
    3xxRedirection301 (Moved Permanently), 302 (Found)
    4xxClient Error400 (Bad Request), 404 (Not Found)
    5xxServer Error500 (Internal Server Error), 503 (Service Unavailable)

    Each status code verb essentially represents the result of the action performed by the server in response to the client request.

    API keys:

    What are API Keys?

    An API key is a unique identifier used to authenticate requests to an API. It acts like a password to ensure that only authorized users can access a service.

    How API Keys Work:

    1. Request: You make an API request with the API key included.
    2. Authentication: The API verifies the key to confirm you have permission.
    3. Response: If valid, the API sends back the requested data.
    Example: Using API Key in Python:
    import requests

    url = 'https://api.example.com/data'
    api_key = 'your_api_key_here'

    # Include API key in headers
    headers = {'Authorization': f'Bearer {api_key}'}

    # Send GET request
    response = requests.get(url, headers=headers)

    if response.status_code == 200:
        print("Data:", response.json())
    else:
        print("Error:", response.status_code)

    Types of API Key Authentication:

    1. API Key in Request Header:

      • The API key is passed via the Authorization header, which is a secure method.
      • Example:
        headers = {'Authorization': f'Bearer {api_key}'}
        response = requests.get(url, headers=headers)
    2. API Key as URL Query Parameter:

      • The API key is appended directly to the URL as a query parameter.
      • Example:

        params = {'api_key': api_key} response = requests.get(url, params=params)
      • Note: This method is less secure since the key can be exposed in URLs or logs.
    3. API Key in Request Body (POST Requests):

      • The API key is included in the body of a POST request along with other data.
      • Example:
        data = {'api_key': api_key, 'param1': 'value1', 'param2': 'value2'}
        response = requests.post(url, json=data)
      • Used for more sensitive operations, as it hides the key from URL logs.

    Summary of API Key Authentication Methods:

    • Headers: Most secure method, commonly used (Authorization: Bearer {api_key}).
    • Query Parameters: Easier to implement but less secure (?api_key=your_api_key_here).
    • Request Body: Used for POST requests and sensitive operations, key is not exposed in the URL.

    Best Practices:

    • Keep your API keys secure: Do not expose them in public repositories.
    • Regenerate keys regularly for security.
    • Store keys in environment variables or configuration files.

    What is a JWT (JSON Web Token)? (ultimately it is an API key)

    A JWT is a way to securely send information between two parties (usually a server and a client). It is often used in authentication (verifying who you are) and authorization (checking what you're allowed to do).

    Think of a JWT as a ticket that proves who you are and what you're allowed to do. This ticket is used to access protected parts of a website or app.

    JSON tokens looks like key-value pairs

    Structure of a JWT:

    A JWT is made up of three parts:

    1. Header: Describes how the JWT is signed (like the type of security used).
    2. Payload: Contains the actual data (like the user’s ID or username).
    3. Signature: A secret code that protects the token from being changed by someone else.

    These parts are joined by dots (.) to create the full JWT.

    Header.Payload.Signature

    Example: How JWT Works

    1. Login: You enter your username and password on a website.
    2. Server Creates JWT: If your login is successful, the server creates a JWT containing your information and sends it back to your browser.
    3. Send JWT with Future Requests: For every other request you make (e.g., accessing a protected page), your browser sends the JWT back to the server to prove that you are logged in.
    4. Server Verifies the JWT: The server checks the JWT to make sure it is valid and not tampered with. If it’s valid, the server lets you access the resource.

    Why Use JWT?

    • Stateless: The server doesn’t need to remember who you are, because the JWT itself contains all the information needed.
    • Secure: Since the JWT is signed, it can’t be easily changed by anyone.
    • Portable: JWTs are compact and can be used across different platforms (web, mobile apps, etc.).

    Simple Program to Create and Decode JWT:


    import jwt import datetime # Secret key used to sign the JWT secret_key = "my_secret_key" # Create a JWT payload = { 'user_id': 1, # Example user ID 'username': 'john_doe', # Example username 'exp': datetime.datetime.utcnow() + datetime.timedelta(seconds=30) # Token expires in 30 seconds } # Encode the JWT token = jwt.encode(payload, secret_key, algorithm='HS256') print("Generated JWT Token:", token) # Decode the JWT (for verification) decoded_payload = jwt.decode(token, secret_key, algorithms=['HS256']) print("\nDecoded Payload:", decoded_payload)

    Key Points:

    • Create the Token: The token is created using the jwt.encode() method, which takes the payload (data) and signs it with a secret key.
    • Decode the Token: The jwt.decode() method is used to decode the token back into a readable format.

    Expected Output:


    Generated JWT Token: <some long string> Decoded Payload: {'user_id': 1, 'username': 'john_doe', 'exp': datetime.datetime(...)}

    What the Program Does:

    1. Generates a JWT token with user data and an expiration time (30 seconds from now).
    2. Prints the token so you can see what the JWT looks like.
    3. Decodes the token back into the original data (the payload) using the secret key.

    This simple example will help you understand the basics of how JWT works!


    python/rama_openweather_api_assignment.ipynb at main · ramapathakota05/python - link to API assignment


    ===================================================================

    JSON vs Python dict

    You can think of JSON as a string format where the data is represented as key-value pairs. Even though JSON and Python dictionaries look similar, in JSON, all values are treated as strings, even if they represent numbers. To manipulate the data in Python, we need to convert JSON into a Python dictionary so that the data types (like integers or booleans) can be properly recognized and worked with.

    • JSON is a string format that represents data in a human-readable form (key-value pairs). Even if there are numbers in JSON, they are still treated as text (strings), and that's why you need to convert them when you want to manipulate the data.
    • JSON and Python dictionaries (dicts) look similar, but they serve different purposes: JSON is for storing or exchanging data (in files, APIs, etc.), while a Python dict is an actual object you can work with in your code (perform operations on, modify, loop through, etc.).
    • To manipulate data in Python, you need to convert JSON into a Python dict using json.loads(), so Python can work with the data in its proper format (numbers, booleans, etc.) instead of treating everything as a string....note:response.json() internally uses the json.loads() function..so when we say response.json() internally converts json to python dict

    Example:

    1. JSON String (looks like a dict):

      '{"name": "John", "age": 30}'
      
    2. Converted to Python dict:

      {'name': 'John', 'age': 30}
      

    Now, you can easily access or manipulate the values (age, for example) as integers, instead of dealing with them as strings!


    SUMMARY:

    Sure! Here's a more descriptive summary for each topic:

    API Calls

    • Requests Library: requests is a simple HTTP library in Python for sending HTTP requests like GET, POST, PUT, DELETE. It helps you interact with web servers or APIs by handling HTTP communication, including status codes, response data, and headers.
    • Installation: Install requests using python -m pip install requests to easily interact with web services.
    • GET Request: Use requests.get('url') to retrieve data from a URL. It sends an HTTP GET request to fetch information from a server.
    • Response Data:
      • r.status_code: It shows the HTTP status code indicating the result of your request (e.g., 200 means OK, 404 means Not Found).
      • r.text: Raw content returned by the server in text format (HTML, plain text).
      • r.json(): If the server returns data in JSON format, .json() converts the response to a Python dictionary.

    Passing Parameters in URLs

    • Query Parameters: Query parameters are key-value pairs added to the URL after ?. They allow you to pass information to the server (e.g., https://api.example.com/data?key=value).
    • requests.get(): Instead of manually formatting the URL, use the params argument to pass parameters as a dictionary (e.g., payload = {'key': 'value'}).
    • Automatic Encoding: The requests library automatically encodes and appends the parameters to the URL, making it easier and safer to send data in requests without manual encoding.

    API Client-Server Architecture in Python

    • Client: The client (usually a Python script or application) sends HTTP requests to the server. The client is responsible for interacting with the API and processing the response.
    • Server: The server handles the request, processes it (e.g., querying a database), and sends a response (usually in JSON format).
    • Authentication: Many APIs require authentication using API keys or OAuth tokens to ensure that only authorized users can access the data. This helps secure the client-server communication.
    • Error Handling: Clients should be able to handle different server errors like 401 (Unauthorized) or 429 (Too Many Requests) and respond accordingly, ensuring smooth communication with the server.

    HTTP Verbs (Methods)

    • GET: Used to retrieve data from the server. It's like asking the server, "Give me this data."
    • POST: Used to send or create data on the server. It's used when submitting data or creating resources (e.g., sending a form).
    • PUT: Used to update existing data on the server. It's like saying, "Replace this data with new data."
    • DELETE: Used to remove data from the server. It's asking, "Delete this data."

    HTTP Status Codes

    • 1xx (Informational): Indicates that the request is being processed (e.g., 100 – Continue).
    • 2xx (Success): Indicates that the request was successful (e.g., 200 – OK, 201 – Created).
    • 3xx (Redirection): Tells the client to go to a different URL (e.g., 301 – Moved Permanently).
    • 4xx (Client Error): Indicates issues with the request from the client (e.g., 400 – Bad Request, 404 – Not Found).
    • 5xx (Server Error): Indicates a problem on the server side (e.g., 500 – Internal Server Error).

    API Keys

    • API Key: An API key is a unique string used to authenticate requests to an API. It acts like a password and helps the API know which user is making the request.
    • How it Works: When making an API request, you include the API key in the request header or query parameters. The API validates the key to ensure you're authorized.
      • In Headers: Secure method, used with Authorization: Bearer {api_key}.
      • In URL: Less secure, passed as query parameters (e.g., ?api_key=your_api_key_here).
      • In Request Body: Used with POST requests, included in the request data to hide the key from URLs.

    JWT (JSON Web Token)

    • JWT: A compact and secure way to send information between two parties (e.g., client and server). It is often used for user authentication and authorization.
    • Structure:
      • Header: Information about how the JWT is signed.
      • Payload: Contains user data or claims (e.g., user ID, role).
      • Signature: A secret key to verify that the JWT has not been tampered with.
    • How It Works:
      1. User logs in → Server creates JWT with user info.
      2. JWT sent back to the client.
      3. On future requests, the client sends the JWT to verify identity.
      4. Server validates the JWT to allow access.

    JSON vs Python dict

    You can think of JSON as a string format where the data is represented as key-value pairs. Even though JSON and Python dictionaries look similar, in JSON, all values are treated as strings, even if they represent numbers. To manipulate the data in Python, we need to convert JSON into a Python dictionary so that the data types (like integers or booleans) can be properly recognized and worked with.

    Previous Post Next Post