Manipulating HTTP Requests

Learn how to intercept and modify HTTP requests in your application. This guide walks you through customizing request headers, URLs, and parameters, giving you full control over how your requests are sent and managed.

When interacting with DRM, HLS Playlist, or other types of media requests, there might be instances where you need to adjust or manipulate the HTTP requests before they are sent.

This is where preprocessHttpRequest comes into play.

In this guide, we’ll explain how this handler works, why you might want to use it, and how you can easily implement it to customize your HTTP requests.

What is preprocessHttpRequest?

It is a tool that allows you to modify HTTP request parameters just before they are sent out. This means you have the power to alter things like request headers, URLs, and other configurations depending on your specific needs.

Why Would You Want to Modify HTTP Requests?

There are several scenarios where customizing HTTP requests could be useful:

  • Adding Security Tokens: you might need to attach specific authorization tokens or other security credentials to requests, especially for DRM (Digital Rights Management) protected content.
  • Adjusting URLs: sometimes, you may need to redirect requests to different endpoints or append query parameters.
  • Custom Logging or Analytics: by modifying requests, you can track certain behaviors or conditions in your system, helping with analytics or debugging.

How to Use preprocessHttpRequest

Using the preprocessHttpRequest property is straightforward. Here’s how you can set it up and customize your HTTP requests.

Assign the Handler via a closure

You will assign a closure to the preprocessHttpRequest property of your network config. The closure will conform to the PreprocessHttpRequestHandler type and contain the logic for modifying your requests.

playerConfig.networkConfig.preprocessHttpRequest = { type, request, completionHandler in
    var modifiedRequest = request

    switch type {
    case .drmLicenseFairplay:
        // Example: Add an Authorization header for DRM requests
        modifiedRequest.headers["Authorization"] = "Bearer someAccessToken"
		case .manifestHlsMaster:
        // Example: Modify the URL for HLS Playlist requests
        modifiedRequest.url = modifiedRequest.url.appendingPathComponent("modified")
    default:
      	break
    }

    // Call the completion handler with the modified request
    completionHandler(modifiedRequest)
}

Understanding the Process

  • Request Type Identification: the type parameter lets you know what kind of request you’re dealing with (e.g., DRM, HLS Playlist). This helps you apply the right modifications.
  • Modify the Request: you have full access to the request object, allowing you to change headers, URLs, or anything else.
  • Completion Handler: it’s crucial to call the completionHandler with your modified request. This ensures the request is sent out with your custom changes.

Practical example

Imagine you need to ensure that all DRM requests include a specific authorization token. Without the token, the request would fail, preventing content from being accessed.

Here’s a simple way to do that:

struct ContentView: View {
    private let player: Player

    init() {
        let playerConfig = PlayerConfig()
        playerConfig.networkConfig.preprocessHttpRequest = { type, request, completionHandler in
            var modifiedRequest = request

            switch type {
            case .drmLicenseFairplay:
                modifiedRequest.headers["Authorization"] = "Bearer secureToken123"
            default:
                break
            }
            completionHandler(modifiedRequest)
        }
        player = PlayerFactory.createPlayer()
    }
    ...
}

Now, every time a DRM request is made, it will automatically include the required authorization token.

Limitations

While the preprocessHttpRequest is powerful, there are a few things to keep in mind:

  • Supported Request Types: currently key HLS AES (key/hls/aes) requests are not supported. Subtitle media (media/subtitles) requests are only supported in case the subtitles are side-loaded. Unsupported requests won’t be processed through this handler.
  • Critical Timing: it’s essential to call the completionHandler with your modified request; otherwise, the HTTP request won’t be sent, and the player might not function as expected.