Practical Applications and Best Practices
Now that you have learned how to set various types of custom headers, let's explore some practical applications and best practices for working with headers in real-world scenarios.
Sending and Receiving JSON Data
When working with modern APIs, JSON is the most common data format. Let's see how to properly set headers for JSON requests:
- Create a new file named
json_requests.py
- Add the following code:
import requests
import json
url = 'https://httpbin.org/post' ## This endpoint accepts POST requests
## Data to send
data = {
'name': 'John Doe',
'email': '[email protected]',
'message': 'Hello, world!'
}
## Set appropriate headers for JSON
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
## Method 1: Using the json parameter (recommended)
print("Method 1: Using the json parameter")
response = requests.post(url, json=data, headers=headers)
print(f"Status Code: {response.status_code}")
print(response.json()['headers']) ## Show the headers received
print(f"\nData sent (as received by server): {response.json()['json']}")
## Method 2: Manually converting to JSON
print("\nMethod 2: Manually converting to JSON")
json_data = json.dumps(data)
response = requests.post(url, data=json_data, headers=headers)
print(f"Status Code: {response.status_code}")
print(response.json()['headers']) ## Show the headers received
print(f"\nData sent (as received by server): {response.json()['json']}")
- Run the script:
python json_requests.py
You should see output similar to:
Method 1: Using the json parameter
Status Code: 200
{'Accept': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'Content-Length': '72', 'Content-Type': 'application/json', 'Host': 'httpbin.org', 'X-Amzn-Trace-Id': 'Root=1-6430ab12-abc123def456'}
Data sent (as received by server): {'name': 'John Doe', 'email': '[email protected]', 'message': 'Hello, world!'}
Method 2: Manually converting to JSON
Status Code: 200
{'Accept': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'Content-Length': '72', 'Content-Type': 'application/json', 'Host': 'httpbin.org', 'X-Amzn-Trace-Id': 'Root=1-6430ab13-abc123def456'}
Data sent (as received by server): {'name': 'John Doe', 'email': '[email protected]', 'message': 'Hello, world!'}
Note that both methods work, but Method 1 is more convenient because the Requests library handles the JSON conversion for you.
If you need to make multiple requests with the same headers, using a Session
object can save time and make your code cleaner:
- Create a new file named
session_headers.py
- Add the following code:
import requests
## Create a session object
session = requests.Session()
## Set default headers for all requests made with this session
session.headers.update({
'User-Agent': 'MyCustomApp/1.0',
'Accept-Language': 'en-US,en;q=0.9',
'X-API-Key': 'my_session_api_key'
})
## Make a request using the session - it will include our default headers
print("First request with session:")
response = session.get('https://httpbin.org/headers')
print(response.json())
## Add a custom header just for this request
print("\nSecond request with additional header:")
response = session.get('https://httpbin.org/headers',
headers={'X-Custom-Header': 'Just for this request'})
print(response.json())
## Original headers remain unchanged for future requests
print("\nThird request (original headers only):")
response = session.get('https://httpbin.org/headers')
print(response.json())
- Run the script:
python session_headers.py
You should see output similar to:
First request with session:
{'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'en-US,en;q=0.9', 'Host': 'httpbin.org', 'User-Agent': 'MyCustomApp/1.0', 'X-API-Key': 'my_session_api_key', 'X-Amzn-Trace-Id': 'Root=1-6430ab45-abc123def456'}}
Second request with additional header:
{'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'en-US,en;q=0.9', 'Host': 'httpbin.org', 'User-Agent': 'MyCustomApp/1.0', 'X-API-Key': 'my_session_api_key', 'X-Custom-Header': 'Just for this request', 'X-Amzn-Trace-Id': 'Root=1-6430ab46-abc123def456'}}
Third request (original headers only):
{'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'en-US,en;q=0.9', 'Host': 'httpbin.org', 'User-Agent': 'MyCustomApp/1.0', 'X-API-Key': 'my_session_api_key', 'X-Amzn-Trace-Id': 'Root=1-6430ab47-abc123def456'}}
Using sessions is a best practice for several reasons:
- Improved performance (connection pooling)
- Consistent headers across requests
- Automatic cookie handling
- Ability to add per-request customization when needed
To wrap up, here are some best practices to follow when working with HTTP headers:
- Use Session Objects for multiple requests to the same domain
- Set Content-Type Headers correctly for the data you're sending
- Handle Authentication Properly - use built-in auth when possible
- Keep Sensitive Information Secure - don't hardcode API keys or tokens
- Follow API Documentation carefully for required headers
Here's a final example that demonstrates these best practices:
- Create a new file named
best_practices.py
- Add the following code:
import requests
import os
## In a real application, get these from environment variables or a secure configuration
## For this example, we're keeping it simple
API_KEY = os.environ.get('API_KEY', 'default_api_key')
BASE_URL = 'https://httpbin.org'
def create_api_client():
"""Create a reusable session with default headers."""
session = requests.Session()
## Set common headers
session.headers.update({
'User-Agent': 'MyApp/1.0',
'X-API-Key': API_KEY,
'Accept': 'application/json'
})
return session
def get_data(client, endpoint):
"""Make a GET request to the specified endpoint."""
url = f"{BASE_URL}/{endpoint}"
response = client.get(url)
return response.json()
def post_data(client, endpoint, data):
"""Make a POST request with JSON data."""
url = f"{BASE_URL}/{endpoint}"
response = client.post(url, json=data)
return response.json()
## Usage example
def main():
## Create the API client
client = create_api_client()
## GET request example
print("Making GET request...")
get_response = get_data(client, 'headers')
print(f"Headers sent: {get_response['headers']}")
## POST request example
print("\nMaking POST request...")
data = {'name': 'John', 'age': 30}
post_response = post_data(client, 'post', data)
print(f"Data received by server: {post_response['json']}")
if __name__ == '__main__':
main()
- Run the script:
python best_practices.py
You should see output similar to:
Making GET request...
Headers sent: {'Accept': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'Host': 'httpbin.org', 'User-Agent': 'MyApp/1.0', 'X-API-Key': 'default_api_key', 'X-Amzn-Trace-Id': 'Root=1-6430ab78-abc123def456'}
Making POST request...
Data received by server: {'name': 'John', 'age': 30}
This example demonstrates a structured approach to making HTTP requests with custom headers, following best practices like creating reusable sessions, organizing code into functions, and avoiding hardcoded sensitive information.