Skip to content

Commit 6e48539

Browse files
jkwluiBenjamin E. Coe
andauthored
fix(v4-policy): encode special characters (#1169)
* fix(v4-policy): encode special characters * test special character encoding Co-authored-by: Benjamin E. Coe <bencoe@google.com>
1 parent 15ba795 commit 6e48539

File tree

4 files changed

+44
-8
lines changed

4 files changed

+44
-8
lines changed

conformance-test/v4SignedUrl.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -220,16 +220,15 @@ describe('v4 conformance test', () => {
220220

221221
assert.strictEqual(policy.url, testCase.policyOutput.url);
222222
const outputFields = testCase.policyOutput.fields;
223-
const decodedPolicy = Buffer.from(
224-
policy.fields.policy,
225-
'base64'
226-
).toString();
223+
const decodedPolicy = JSON.parse(
224+
Buffer.from(policy.fields.policy, 'base64').toString()
225+
);
227226
assert.deepStrictEqual(
228227
decodedPolicy,
229-
testCase.policyOutput.expectedDecodedPolicy
228+
JSON.parse(testCase.policyOutput.expectedDecodedPolicy)
230229
);
231230

232-
assert.deepStrictEqual(outputFields, testCase.policyOutput.fields);
231+
assert.deepStrictEqual(policy.fields, outputFields);
233232

234233
fakeTimer.restore();
235234
});

src/file.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ import {
6363
} from '@google-cloud/common/build/src/util';
6464
// eslint-disable-next-line @typescript-eslint/no-var-requires
6565
const duplexify: DuplexifyConstructor = require('duplexify');
66-
import {normalize, objectKeyToLowercase} from './util';
66+
import {normalize, objectKeyToLowercase, unicodeJSONStringify} from './util';
6767
import {GaxiosError, Headers, request as gaxiosRequest} from 'gaxios';
6868

6969
export type GetExpirationDateResponse = [Date];
@@ -2611,7 +2611,7 @@ class File extends ServiceObject<File> {
26112611
expiration,
26122612
};
26132613

2614-
const policyString = JSON.stringify(policy);
2614+
const policyString = unicodeJSONStringify(policy);
26152615
const policyBase64 = Buffer.from(policyString).toString('base64');
26162616

26172617
try {

src/util.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,16 @@ export function objectKeyToLowercase<T>(object: {[key: string]: T}) {
9090
}
9191
return newObj;
9292
}
93+
94+
/**
95+
* JSON encode str, with unicode \u+ representation.
96+
* @param {object} obj The object to encode.
97+
* @return {string} Serialized string.
98+
*/
99+
export function unicodeJSONStringify(obj: object) {
100+
return JSON.stringify(obj).replace(
101+
/[\u0080-\uFFFF]/g,
102+
(char: string) =>
103+
'\\u' + ('0000' + char.charCodeAt(0).toString(16)).slice(-4)
104+
);
105+
}

test/file.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2941,6 +2941,30 @@ describe('File', () => {
29412941
);
29422942
});
29432943

2944+
it('should encode special characters in policy', done => {
2945+
CONFIG = {
2946+
fields: {
2947+
'x-goog-meta-foo': 'bår',
2948+
},
2949+
...CONFIG,
2950+
};
2951+
2952+
file.generateSignedPostPolicyV4(
2953+
CONFIG,
2954+
(err: Error, res: SignedPostPolicyV4Output) => {
2955+
assert.ifError(err);
2956+
2957+
assert.strictEqual(res.fields['x-goog-meta-foo'], 'bår');
2958+
const decodedPolicy = Buffer.from(
2959+
res.fields.policy,
2960+
'base64'
2961+
).toString('utf-8');
2962+
assert(decodedPolicy.includes('"x-goog-meta-foo":"b\\u00e5r"'));
2963+
done();
2964+
}
2965+
);
2966+
});
2967+
29442968
it('should not include fields with x-ignore- prefix in conditions', done => {
29452969
CONFIG = {
29462970
fields: {

0 commit comments

Comments
 (0)