@@ -6,10 +6,11 @@ import app from '../app'
66import { getConfig , mergeConfig } from '../config'
77import { signJWT } from '@internal/auth'
88import { Obj , backends } from '../storage'
9- import { useMockObject , useMockQueue } from './common'
9+ import { getInvalidObjectName , getUnicodeObjectName , useMockObject , useMockQueue } from './common'
1010import { getServiceKeyUser , getPostgresConnection } from '@internal/database'
1111import { Knex } from 'knex'
1212import { ErrorCode , StorageBackendError } from '@internal/errors'
13+ import { randomUUID } from 'crypto'
1314
1415const { jwtSecret, serviceKey, tenantId } = getConfig ( )
1516const anonKey = process . env . ANON_KEY || ''
@@ -2456,3 +2457,90 @@ describe('testing list objects', () => {
24562457 expect ( responseJSON [ 1 ] . name ) . toBe ( 'sadcat-upload23.png' )
24572458 } )
24582459} )
2460+
2461+ describe ( 'Object key with Unicode characters' , ( ) => {
2462+ test ( 'can upload, get and list' , async ( ) => {
2463+ const prefix = `test-utf8-${ randomUUID ( ) } `
2464+ const objectName = getUnicodeObjectName ( )
2465+
2466+ const form = new FormData ( )
2467+ form . append ( 'file' , fs . createReadStream ( `./src/test/assets/sadcat.jpg` ) )
2468+ const headers = Object . assign ( { } , form . getHeaders ( ) , {
2469+ authorization : `Bearer ${ serviceKey } ` ,
2470+ 'x-upsert' : 'true' ,
2471+ } )
2472+
2473+ const uploadResponse = await app ( ) . inject ( {
2474+ method : 'POST' ,
2475+ url : `/object/bucket2/${ prefix } /${ encodeURIComponent ( objectName ) } ` ,
2476+ headers : {
2477+ ...headers ,
2478+ ...form . getHeaders ( ) ,
2479+ } ,
2480+ payload : form ,
2481+ } )
2482+ expect ( uploadResponse . statusCode ) . toBe ( 200 )
2483+
2484+ const getResponse = await app ( ) . inject ( {
2485+ method : 'GET' ,
2486+ url : `/object/bucket2/${ prefix } /${ encodeURIComponent ( objectName ) } ` ,
2487+ headers : {
2488+ authorization : `Bearer ${ serviceKey } ` ,
2489+ } ,
2490+ } )
2491+ expect ( getResponse . statusCode ) . toBe ( 200 )
2492+ expect ( getResponse . headers [ 'etag' ] ) . toBe ( 'abc' )
2493+ expect ( getResponse . headers [ 'last-modified' ] ) . toBe ( 'Thu, 12 Aug 2021 16:00:00 GMT' )
2494+ expect ( getResponse . headers [ 'cache-control' ] ) . toBe ( 'no-cache' )
2495+
2496+ const listResponse = await app ( ) . inject ( {
2497+ method : 'POST' ,
2498+ url : `/object/list/bucket2` ,
2499+ headers : {
2500+ authorization : `Bearer ${ serviceKey } ` ,
2501+ } ,
2502+ payload : { prefix } ,
2503+ } )
2504+ expect ( listResponse . statusCode ) . toBe ( 200 )
2505+ const listResponseJSON = JSON . parse ( listResponse . body )
2506+ expect ( listResponseJSON ) . toHaveLength ( 1 )
2507+ expect ( listResponseJSON [ 0 ] . name ) . toBe ( objectName . split ( '/' ) [ 0 ] )
2508+
2509+ const deleteResponse = await app ( ) . inject ( {
2510+ method : 'DELETE' ,
2511+ url : `/object/bucket2/${ prefix } /${ encodeURIComponent ( objectName ) } ` ,
2512+ headers : {
2513+ authorization : `Bearer ${ serviceKey } ` ,
2514+ } ,
2515+ } )
2516+ expect ( deleteResponse . statusCode ) . toBe ( 200 )
2517+ } )
2518+
2519+ test ( 'should not be allowed to upload objects with invalid names' , async ( ) => {
2520+ const invalidObjectName = getInvalidObjectName ( )
2521+ const form = new FormData ( )
2522+ form . append ( 'file' , fs . createReadStream ( `./src/test/assets/sadcat.jpg` ) )
2523+ const headers = Object . assign ( { } , form . getHeaders ( ) , {
2524+ authorization : `Bearer ${ serviceKey } ` ,
2525+ 'x-upsert' : 'true' ,
2526+ } )
2527+ const uploadResponse = await app ( ) . inject ( {
2528+ method : 'POST' ,
2529+ url : `/object/bucket2/${ encodeURIComponent ( invalidObjectName ) } ` ,
2530+ headers : {
2531+ ...headers ,
2532+ ...form . getHeaders ( ) ,
2533+ } ,
2534+ payload : form ,
2535+ } )
2536+ expect ( uploadResponse . statusCode ) . toBe ( 400 )
2537+ expect ( S3Backend . prototype . uploadObject ) . not . toHaveBeenCalled ( )
2538+ expect ( uploadResponse . body ) . toBe (
2539+ JSON . stringify ( {
2540+ statusCode : '400' ,
2541+ error : 'InvalidKey' ,
2542+ message : `Invalid key: ${ encodeURIComponent ( invalidObjectName ) } ` ,
2543+ } )
2544+ )
2545+ } )
2546+ } )
0 commit comments