1
-
2
1
type SASinput = {
3
2
accountKey : string
4
3
accountName : string
@@ -23,11 +22,12 @@ const truncatedISO8061Date = (date: Date) => {
23
22
return dateString . substring ( 0 , dateString . length - 5 ) + 'Z'
24
23
}
25
24
26
- const computeHMACSHA256 = async ( stringToSign : string , accountKey : string ) => {
25
+ const computeHMACSHA256 = async ( stringToSign : string , accountKey : string ) : Promise < string > => {
27
26
const enc = new TextEncoder ( )
28
27
const signatureUTF8 = enc . encode ( stringToSign )
29
28
const key = await crypto . subtle . importKey (
30
29
'raw' ,
30
+ //@ts -ignore
31
31
Buffer . from ( accountKey , 'base64' ) ,
32
32
{
33
33
name : 'HMAC' ,
@@ -41,6 +41,7 @@ const computeHMACSHA256 = async (stringToSign: string, accountKey: string) => {
41
41
42
42
const digest = await crypto . subtle . sign ( 'HMAC' , key , signatureUTF8 )
43
43
44
+ //@ts -ignore
44
45
return Buffer . from ( digest ) . toString ( 'base64' )
45
46
}
46
47
@@ -57,39 +58,51 @@ const getSASqueryParams = async (input: SASinput) => {
57
58
const version = '2018-11-09'
58
59
const signedSnapshotTime = undefined
59
60
60
- const stringToSign = [
61
- input . permissions ? input . permissions : '' ,
62
- input . startsOn ? truncatedISO8061Date ( input . startsOn ) : '' ,
63
- truncatedISO8061Date ( input . expiresOn ) ,
64
- getCanonicalName ( input . accountName , input . containerName , input . blobName ) ,
65
- input . identifier ? input . identifier : '' ,
66
- input . ipRange ? input . ipRange : '' ,
67
- input . protocol ? input . protocol : '' ,
68
- version ,
69
- resource ,
70
- signedSnapshotTime ,
71
- input . cacheControl ? input . cacheControl : '' ,
72
- input . contentDisposition ? input . contentDisposition : '' ,
73
- input . contentEncoding ? input . contentEncoding : '' ,
74
- input . contentLanguage ? input . contentLanguage : '' ,
75
- input . contentType ? input . contentType : '' ,
76
- ] . join ( '\n' )
61
+ let queryParams = {
62
+ sp : input . permissions ?? '' ,
63
+ st : input . startsOn ? truncatedISO8061Date ( input . startsOn ) : '' ,
64
+ se : truncatedISO8061Date ( input . expiresOn ) ,
65
+ name : getCanonicalName ( input . accountName , input . containerName , input . blobName ) ,
66
+ si : input . identifier ?? '' ,
67
+ sip : input . ipRange ?? '' ,
68
+ spr : input . protocol ?? '' ,
69
+ sv : version ,
70
+ sr : resource ,
71
+ ne : signedSnapshotTime ,
72
+ rscc : input . cacheControl ?? '' ,
73
+ rscd : input . contentDisposition ?? '' ,
74
+ rsce : input . contentEncoding ?? '' ,
75
+ rscl : input . contentLanguage ?? '' ,
76
+ rsct : input . contentType ?? '' ,
77
+ }
78
+
79
+ const stringToSign = Object . values ( queryParams ) . join ( '\n' )
77
80
78
81
const signature = await computeHMACSHA256 ( stringToSign , input . accountKey )
82
+ const { name, ne, ...rest } = queryParams
79
83
80
- return `sv=${ version } &spr=https&se=${ encodeURIComponent (
81
- truncatedISO8061Date ( input . expiresOn )
82
- ) } &sr=b&sp=rw&sig=${ encodeURIComponent ( signature ) } `
84
+ //@ts -ignore
85
+ queryParams . sig = signature
86
+
87
+ return Object . keys ( { ...rest , ...{ sig : signature } } )
88
+ . map ( ( key ) => {
89
+ if ( queryParams [ key ] === '' ) return
90
+
91
+ return `${ key } =${ encodeURIComponent ( queryParams [ key ] ) } `
92
+ } )
93
+ . join ( '&' )
83
94
}
84
95
85
- export default async ( input : SASinput ) => {
86
- const url = [ input . containerName , input . blobName ] . filter ( el => el ) . join ( '/' )
96
+ const createBlobSas = async ( input : SASinput ) => {
97
+ const url = [ input . containerName , input . blobName ] . filter ( ( el ) => el ) . join ( '/' )
87
98
const storageUri = new URL ( url , `https://${ input . accountName } .blob.core.windows.net` )
88
99
const queryParams = await getSASqueryParams ( input )
89
100
90
101
storageUri . search = queryParams
91
102
92
103
return {
93
- blobSasUrl : url . toString ( ) ,
104
+ blobSasUrl : storageUri . toString ( ) ,
94
105
}
95
106
}
107
+
108
+ export { createBlobSas }
0 commit comments