Netnhost is founded by highly skilled and motivated IT entrepreneurs. It’s a team of people that who are creative and can work for a greater extent to make our clients happy.
Save-Data: on
when the mobile phone OS suggests it (detailed explanation in the following section). Upon receiving the request, CloudFront matches the request URL with corresponding path patterns. In the example, CloudFront will match any request and trigger the CloudFront Function on the Viewer Request event class. Then, the CloudFront Function will modify and forward the request to obtain the correct variant of the content based on the presence or absence of the header.
nw_path_monitor_t
observer, to monitor the network path that’s available to the device. As a phone or tablet moves from Wi-Fi coverage to cellular data coverage or back again, the app receives call-backs to a handler, indicating that the network path has been updated. In our handler code, we interrogate the path capabilities using the calls nw_path_is_expensive()
and nw_path_is_constrained()
. The former tells us whether or not the path uses an interface that is considered expensive, such as cellular or a personal hotspot. The latter checks whether or not the path uses a network interface that is in Low Data mode (see below). Note that iOS doesn’t provide more granular information about the exact type of cellular network to which the device is attached.
Exactly how we use this data regarding the path capabilities is an application-level choice. For example, if our application streams video, then we may decide to use the expensive flag to select standard resolution video instead of 4K or 8K. This is because we can rapidly exhaust a customer’s cellular data plan if we stream high resolution video across a cellular network. In this case, it may also be logical to combine this information with other device capability information, such as screen size and resolution. Furthermore, CloudFront can infer the broad category of device the client is running on, and add headers such as CloudFront-Is-Mobile-Viewer: true
to requests for you, as described here.
On the other hand, we may wish to preserve an element of user choice in the type of asset delivered—after all, our user may be perfectly willing to use their cellular data plan allowance to download their favorite show in the best possible quality. We could use an application-specific, or even user profile-specific setting within the app, or alternatively—and as shown in the sample code—we can use the constrained flag. This will be true if the user has turned on Low Data mode for the relevant data plan in the iOS Settings app (Settings > Mobile Data > Mobile Data Options > Low Data Mode toggle). This setting provides an easily-understood, device-wide hint that the user wishes to limit the usage of their cellular data plan, which makes it a logical choice here.
When we’ve detected that reduced-size assets are desired, as described above, we add a request header Save-Data: on
to each HTTP request that we send. If regular-sized assets are desired, we omit this header altogether. The sample app uses the Apple URL Loading System, embodied by NSURLSession
and NSURLSessionTask
objects, to load web-hosted assets. All we need to do is configure an NSURLSession
object with the additional request header field as required, as shown in this code snippet:
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSDictionary *myHeaders = nil;
// Here we just use the pathConstrained flag to influence our
// added HTTP request headers; we could do something more complex
// using both flags
if (pathConstrained) {
// Add Save-Data: On header
myHeaders = [NSDictionary dictionaryWithObject:@"on" forKey:@"Save-Data"];
[config setHTTPAdditionalHeaders:myHeaders];
}
session = [NSURLSession sessionWithConfiguration:config];
pathConstrained
is true, then when we now use the session object to create download tasks, underlying HTTP requests that are sent to the HTTP origin will contain the request header field Save-Data: on
.
/save
. Next, set up CloudFront:
/save
to the URL if the header Save-Data
is present and has the value on
.
function handler(event) {
var request = event.request;
var headers = request.headers;
if (headers['save-data'] && headers['save-data']['value'] === 'on') {
var url = request['uri'];
var newurl = '/save' + url;
// we log the url
console.log(newurl);
request.uri = newurl;
}
return request;
}
Save-Data: on
header, it will redirect the request to /save
. In the next section, we’ll see two ways to test it.
For simplicity of this example, we have configured this function to run for any object that is requested from the CloudFront distribution. In practice, you can use the Behaviors tab of the CloudFront distribution to limit its application only to certain URI path patterns—such as /media/mpeg/*.mp4
, or /images/*.jpg
—where optimized media is known to exist in the corresponding bucket prefixes /save/media/mpeg/
and /save/images/
. This is useful for situations where some media has been optimized, but media found in other URI paths, perhaps such as legacy assets or UI elements, does not have an optimized variant.
/example.jpg
into the text field and select Fetch. Depending on your connectivity, as described above, the app either will or won’t include the Save-Data: on
header, and the CloudFront distribution will return the appropriate image—see figures 3(b) and (c). The app also shows the size of the downloaded object.
To force your device to use a constrained network path, go into the iOS Settings app. First disable Wi-Fi (Settings > Wi-Fi > Wi-Fi toggle off), and second, enable Low Data Mode for your cellular connection (Settings > Mobile Data > Mobile Data Options > Low Data Mode toggle on).
If you want to test the infrastructure behavior independently of any app, then you can use curl
as follows:
curl https://dXXXXXXXXXXXXX.cloudfront.net/example.jpg --output /tmp/example.jpg
To add the Save-Data: on
header:
curl https://dXXXXXXXXXXXXX.cloudfront.net/example.jpg --header "Save-Data: on" --output /tmp/example.jpg
When you’ve tested the solution, to avoid incurring ongoing costs, first disable and then delete the distribution in the CloudFront console.
nnhadmin