ionic-team / ionic-team/capacitor

[Bug]: HTTP Range Responses not within spec

Open
#8,371 2 comments 0 reactions 0 assignees View on GitHub
triage
Dominant language
TypeScript
Stars
16.7k
Forks
1.3k
Avg merge
3d 15h
Merged PRs (30d)
10

Description

### Capacitor Version

8.1.0

### Other API Details

```Shell

```

### Platforms Affected

- [ ] iOS
- [x] Android
- [ ] Web

### Current Behavior

This issue has been reported: https://github.com/ionic-team/capacitor/issues/7151#issuecomment-1897113728

When constructing the response for an HTTP Range request, the InputStream is not properly truncated at the end of the requested range. This results in the response including data from the specified start index, all the way to the end of the file.

The results of this failed truncation are as follows:
- The `Content-Length` response header gives a byte length that would be correct if the InputStream was truncated
- The `Content-Range` response header gives a byte range that would be correct if the InputStream was truncated

From my understanding of the HTTP Range spec, if the server plans to send the remainder of the file in the response (which is the current behavior of the Capacitor implementation), the Content-Length and Content-Range must be updated to reflect the extra returned length and ending byte range (length - 1).

This appears to cause issues specifically with the PMTiles decoder since it appears to rely on the response headers to understand how much data it received.

#### Reproduction Steps

1. Install dependencies and build app with pnpm (crucial for patches to apply)

```bash
pnpm i
pnpm build
pnpm cap sync android
pnpm cap run android
```

3. Using the demo app, observe a `cstat.pmtiles` request from within Chrome Devtools.
4. You will see a Content-Length header in the response.
5. Convert the Content-Length value to hexadecimal
6. View the Response data tab in Devtools
7. Go to the Hexadecimal index you calculated in Step 3.
8. See that there is lots of data returned that exceeds the Content-Length.
9. You will see that the data continues to the end of the file (`index = totalFileLength - startRange - 1` => Convert to Hex)
#### Example

Request Range: `bytes=850902-889367`
Response `Content-Length` Header: `38466` (0x00009642)
Response `Content-Range` Header: `bytes 850902-889367/3949417`

**Response Data @ 0x00009642**

Image

**Response Data @ 0x002F4792 (See step 7: 3949417-850902-1)**

Image

### Expected Behavior

The stream is properly truncated at the specified byte index or the response headers match the fact that the remainder of the file is sent. Ideally the stream is properly truncated to minimize large data transfer.

### Project Reproduction

https://github.com/bwees/range-request-capacitor-repro/tree/fix/lowercase-range

UPDATE: March 3 17:00 UTC, the example project was broken and has since been fixed

### Additional Information

The provided project branch includes a pnpm patch that resolves issues that are fixed in #8368. This is needed to properly debug this problem as otherwise the range response headers are not sent.

I also took multiple attempts at creating a PR to solve this issue but could not get the stream to properly truncate without a ERR:FAILED error being thrown or the Content-Length header being overridden before response to the client. Maybe someone more versed in the Web Server implementation has some insight but I was not able to solve it

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.