Skip to content

Commit

Permalink
[eas-cli] Detect valid JSON files during hosting upload (#2829)
Browse files Browse the repository at this point in the history
* Use application/json as content type for valid JSON without an extension

* Add changelog

* Pull getContentTypeAsync to a separate function
  • Loading branch information
kadikraman authored Jan 21, 2025
1 parent d2e4cb5 commit 5a16f3d
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ This is the log of notable changes to EAS CLI and related packages.
- Allow filtering by `--fingerprint_hash` in `eas build:list` command. ([#2818](https://github.com/expo/eas-cli/pull/2818) by [@szdziedzic](https://github.com/szdziedzic))

### 🐛 Bug fixes
- Ensure that the AASA file is served with content type application/json ([#2829](https://github.com/expo/eas-cli/pull/2829) by [@kadikraman](https://github.com/kadikraman))

### 🧹 Chores
- Fix logs typos in the `eas deploy` command. ([#2822](https://github.com/expo/eas-cli/pull/2822) by [@kadikraman](https://github.com/kadikraman))
Expand Down
26 changes: 23 additions & 3 deletions packages/eas-cli/src/worker/upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import mime from 'mime';
import { Gzip } from 'minizlib';
import fetch, { Headers, HeadersInit, RequestInit, Response } from 'node-fetch';
import fs, { createReadStream } from 'node:fs';
import { readFile } from 'node:fs/promises';
import path from 'node:path';
import promiseRetry from 'promise-retry';

Expand All @@ -28,6 +29,24 @@ const isCompressible = (contentType: string | null, size: number): boolean => {
}
};

const getContentTypeAsync = async (filePath: string): Promise<string | null> => {
let contentType = mime.getType(path.basename(filePath));

if (!contentType) {
const fileContent = await readFile(filePath, 'utf-8');
try {
// check if file is valid JSON without an extension, e.g. for the apple app site association file
const parsedData = JSON.parse(fileContent);

if (parsedData) {
contentType = 'application/json';
}
} catch {}
}

return contentType;
};

export interface UploadParams extends Omit<RequestInit, 'signal' | 'body'> {
filePath: string;
compress?: boolean;
Expand Down Expand Up @@ -70,14 +89,15 @@ export async function uploadAsync(params: UploadParams): Promise<UploadResult> {
headers: headersInit,
...requestInit
} = params;
const stat = await fs.promises.stat(params.filePath);
const stat = await fs.promises.stat(filePath);
if (stat.size > MAX_UPLOAD_SIZE) {
throw new Error(
`Upload of "${params.filePath}" aborted: File size is greater than the upload limit (>500MB)`
`Upload of "${filePath}" aborted: File size is greater than the upload limit (>500MB)`
);
}

const contentType = mime.getType(path.basename(params.filePath));
const contentType = await getContentTypeAsync(filePath);

return await promiseRetry(
async retry => {
const headers = new Headers(headersInit);
Expand Down

0 comments on commit 5a16f3d

Please sign in to comment.