@@ -4,8 +4,10 @@ import (
4
4
"context"
5
5
"fmt"
6
6
io "io"
7
+ "net/url"
7
8
"os"
8
9
"strings"
10
+ "unicode"
9
11
10
12
"github.com/moby/buildkit/session"
11
13
"github.com/pkg/errors"
@@ -82,6 +84,7 @@ func (sp *fsSyncProvider) handle(method string, stream grpc.ServerStream) (retEr
82
84
}
83
85
84
86
opts , _ := metadata .FromIncomingContext (stream .Context ()) // if no metadata continue with empty object
87
+ opts = decodeOpts (opts )
85
88
86
89
dirName := ""
87
90
name , ok := opts [keyDirName ]
@@ -209,6 +212,8 @@ func FSSync(ctx context.Context, c session.Caller, opt FSSendRequestOpt) error {
209
212
210
213
var stream grpc.ClientStream
211
214
215
+ opts = encodeOpts (opts )
216
+
212
217
ctx = metadata .NewOutgoingContext (ctx , opts )
213
218
214
219
switch pr .name {
@@ -337,3 +342,44 @@ func (e InvalidSessionError) Error() string {
337
342
func (e InvalidSessionError ) Unwrap () error {
338
343
return e .err
339
344
}
345
+
346
+ func encodeOpts (opts map [string ][]string ) map [string ][]string {
347
+ md := make (map [string ][]string , len (opts ))
348
+ for k , v := range opts {
349
+ out := make ([]string , len (v ))
350
+ for i , s := range v {
351
+ out [i ] = encodeStringForHeader (s )
352
+ }
353
+ md [k ] = out
354
+ }
355
+ return md
356
+ }
357
+
358
+ func decodeOpts (opts map [string ][]string ) map [string ][]string {
359
+ md := make (map [string ][]string , len (opts ))
360
+ for k , v := range opts {
361
+ out := make ([]string , len (v ))
362
+ for i , s := range v {
363
+ out [i ], _ = url .QueryUnescape (s )
364
+ }
365
+ md [k ] = out
366
+ }
367
+ return md
368
+ }
369
+
370
+ // encodeStringForHeader encodes a string value so it can be used in grpc header. This encoding
371
+ // is backwards compatible and avoids encoding ASCII characters.
372
+ func encodeStringForHeader (input string ) string {
373
+ var output strings.Builder
374
+ for _ , runeVal := range input {
375
+ // Only encode non-ASCII characters.
376
+ if runeVal > unicode .MaxASCII {
377
+ // Encode each non-ASCII character individually.
378
+ output .WriteString (url .QueryEscape (string (runeVal )))
379
+ } else {
380
+ // Directly append ASCII characters and '*' to the output.
381
+ output .WriteRune (runeVal )
382
+ }
383
+ }
384
+ return output .String ()
385
+ }
0 commit comments