Skip to content

Commit 0e15018

Browse files
author
alxndrsn
committed
s3: fix handling of NULL blob.contentType values
Ref getodk#1351
1 parent 92f1186 commit 0e15018

File tree

6 files changed

+84
-14
lines changed

6 files changed

+84
-14
lines changed

lib/external/s3.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,9 @@ const init = (config) => {
118118
// * https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html#API_GetObject_RequestSyntax
119119
const getRespHeaders = (filename, { contentType }) => ({
120120
'response-content-disposition': contentDisposition(filename),
121-
'response-content-type': contentType,
121+
// "null" is a questionable content-type, but matches current central behaviour
122+
// See: https://github.com/getodk/central-backend/pull/1352
123+
'response-content-type': contentType || 'null',
122124
});
123125

124126
async function urlForBlob(filename, blob) {
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"type": "FeatureCollection",
3+
"features": [
4+
{
5+
"type": "Feature",
6+
"geometry": {
7+
"type": "Point",
8+
"coordinates": [102.0, 0.5]
9+
},
10+
"properties": {
11+
"prop0": "value0"
12+
}
13+
},
14+
{
15+
"type": "Feature",
16+
"geometry": {
17+
"type": "LineString",
18+
"coordinates": [
19+
[102.0, 0.0],
20+
[103.0, 1.0],
21+
[104.0, 0.0],
22+
[105.0, 1.0]
23+
]
24+
},
25+
"properties": {
26+
"prop0": "value0",
27+
"prop1": 0.0
28+
}
29+
},
30+
{
31+
"type": "Feature",
32+
"geometry": {
33+
"type": "Polygon",
34+
"coordinates": [
35+
[
36+
[100.0, 0.0],
37+
[101.0, 0.0],
38+
[101.0, 1.0],
39+
[100.0, 1.0],
40+
[100.0, 0.0]
41+
]
42+
]
43+
},
44+
"properties": {
45+
"prop0": "value0",
46+
"prop1": { "this": "that" }
47+
}
48+
}
49+
]
50+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
I should not be uploaded with a mime type.
2+
TODO what mime type should I be DOWNLOADED with?

test/e2e/s3/test-forms/1.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@
4949
<value>Smile</value>
5050
<value form="image">jr://images/smile.png</value>
5151
</text>
52+
<text id="geojson">
53+
<value>geojson</value>
54+
<value form="image">jr://images/cities.geojson</value>
55+
</text>
56+
<text id="nomime">
57+
<value>geojson</value>
58+
<value form="image">jr://images/some.nomime</value>
59+
</text>
5260
</translation>
5361
</itext>
5462
<instance>

test/e2e/s3/test.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,13 @@ describe('s3 support', () => {
9090

9191
// given
9292
await setup(1);
93-
await assertNewStatuses({ pending: 11 });
93+
await assertNewStatuses({ pending: 13 });
9494

9595
// when
9696
await cli('upload-pending');
9797

9898
// then
99-
await assertNewStatuses({ uploaded: 11 });
99+
await assertNewStatuses({ uploaded: 13 });
100100
// and
101101
await assertAllRedirect(actualAttachments);
102102
await assertAllDownloadsMatchOriginal(actualAttachments);
@@ -379,7 +379,10 @@ describe('s3 support', () => {
379379

380380
const filepath = `${attDir}/${name}`;
381381

382-
const expectedContentType = mimetypeFor(name);
382+
// "null" is a questionable content-type, but matches current central behaviour
383+
// See: https://github.com/getodk/central-backend/pull/1352
384+
const expectedContentType = mimetypeFor(name) ?? 'null';
385+
383386
const actualContentType = res.headers.get('content-type');
384387
should.equal(actualContentType, expectedContentType);
385388

test/e2e/util/api.js

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ async function apiClient(suiteName, { serverUrl, userEmail, userPassword, logPat
4646
});
4747
} else {
4848
const { body, mimeType } = opts;
49-
return apiPost(path, body, { 'Content-Type':mimeType });
49+
50+
const headers = {};
51+
if(mimeType) headers['Content-Type'] = mimeType;
52+
return apiPost(path, body, headers);
5053
}
5154
}
5255

@@ -99,7 +102,7 @@ async function apiClient(suiteName, { serverUrl, userEmail, userPassword, logPat
99102
if(isRedirected(res)) return new Redirect(res);
100103
if(!res.ok) {
101104
const responseStatus = res.status;
102-
const responseText = await res.text();
105+
const responseText = await res.text() || res.statusText;
103106

104107
const err = new Error(`${responseStatus}: ${responseText}`);
105108
err.responseStatus = responseStatus;
@@ -119,14 +122,16 @@ function mimetypeFor(f) {
119122
// For more, see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
120123
const extension = extname(f);
121124
switch(extension) {
122-
case '.bin' : return 'application/octet-stream';
123-
case '.jpg' : return 'image/jpeg';
124-
case '.png' : return 'image/png';
125-
case '.svg' : return 'image/svg+xml';
126-
case '.txt' : return 'text/plain';
127-
case '.xls' : return 'application/vnd.ms-excel';
128-
case '.xlsx': return 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
129-
case '.xml' : return 'application/xml';
125+
case '.bin' : return 'application/octet-stream';
126+
case '.geojson': return 'application/geo+json';
127+
case '.jpg' : return 'image/jpeg';
128+
case '.nomime' : return null; // used for testing user agents which do not set a mime type for some file extensions
129+
case '.png' : return 'image/png';
130+
case '.svg' : return 'image/svg+xml';
131+
case '.txt' : return 'text/plain';
132+
case '.xls' : return 'application/vnd.ms-excel';
133+
case '.xlsx' : return 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
134+
case '.xml' : return 'application/xml';
130135
default: throw new Error(`Unsure what mime type to use for: ${f}`);
131136
}
132137
}

0 commit comments

Comments
 (0)